Widget development guide
From PrecurioWiki
Welcome to the Precurio Widget Development Guide! The Dev Guide is a practical introduction to developing widgets for Precurio,while introducing concepts of the platform along the way.
This guide is going to have a very pratical approach, which means, we are going to learn how to develop a widget by actually developing one.
Contents |
What is a Widget?
From a user's perspective, a widget is a pod/window on the home page that provides a specific service or information, for example, a calendar or news feed. From an application development perspective, widgets are pluggable mini-modules that provide extended functionality and are designed to run inside a widgets container (which is the home page / dashboard).
Prerequisites
To be able to follow through with this guide,
- An understanding of PHP is a must.
- An understanding of the Zend framework or any other MVC framework, will be helpful
- And ofcourse, you must have installed Precurio.
Our Widget
We are going to try and build the Stock Ticker widget.
Something like the Yahoo Stock Ticker shown below
Don't worry, ours doesn't have to be this stylish.
Our Stock Ticker widget will have the following features
- Display the current price of list of user selected stocks
- User should be able to add and remove a stock (portfolio)
- To add a stock, user can search for stock symbol by entering part of the stock name (e.g. a search for "microsoft" will return "MSFT" )
The View
Now that we are clear on the features of our widget, the first step is to design the appearance of the widget. If you are familiar with html, this should be pretty easy.
But first lets set up our enviroment.
- We create a folder (lets call it "stockwidget") in our web root.
- Create a file 'index.php' in that folder
- Write "This is a test", into 'index.php'
- Navigate to "http://localhost/stockwidget/" to confirm everything is ok (you should see 'This is a test' displayed on your browser)
I won't go into explaining how to design our view, you can download File:Stockwidget.zip to see what I came up with (screenshot shown below).
You will notice the view is static (i.e. non responsive), and contains only html code; That is okay for now, as our priority is to make sure our widget looks the way we imagined it.
Moving to Precurio
Our next step will be to move the view into Precurio and this marks the begining of the "widgetizing process".
All widget views are located in "/precurio/application/widget/views/scripts/",and each view file is located in its own widget folder.
- So we first have to create our widget folder "/precurio/application/widget/views/scripts/stock-ticker/"
Note that we have chosen to call our widget "Stock Ticker" on Precurio (just taking a cue from Yahoo).
Also note the folder name; If your widget name contains two or more words, you seperated them with an hyphen "-"
- Then we rename our 'index.php' to 'index.phtml', and copy it to "/precurio/application/widget/views/scripts/stock-ticker/".
We rename the file because zend views must have the extension ".phtml"
The Controller
Since Precurio is built on an MVC Framework, it means our widget must have a model, a view and a controller. We already have the view, so we are left with the controller and a model.
Let's start with the controller.
All widget controllers are located in the folder "/precurio/application/widget/controllers/" and must extend the Widget_IndexController class located in "/precurio/application/widget/controllers/IndexController.php".
So we create our controller file, StockTickerController.php which contains class Widget_StockTickerController. (note the controller file name; Multiple words are joined together with the first letter of each word capitalized and must begin with a Widget_)
Our StockTickerController.php file looks like this.
<?php /** * StockTickerController.php * * @author Mayor Brain * @version 2.1 */ require_once ('widget/controllers/IndexController.php'); class Widget_StockTickerController extends Widget_IndexController { } ?>
And that's all for the controller. You will notice that the controller for other widgets are also empty, this is because Widget_IndexController already implements the basic functions (actions) needed by a widget.
The Configuration
Before moving on to the model, it's probably a good idea to make Precurio aware of our new widget, so that it appears on the user settings page (you get to user settings by clicking the 'Settings' link beside the 'logout' link).
This involves editing the Precurio configuration file ("/precurio/application/configs/precurio.ini"), so be careful.
- Open the configuration file (precurio.ini)
- Go to the widget section [widget]
This is where Precurio gets all the available widgets
- Insert yours at the end i.e wgt_stock-ticker = "1"
[widget] wgt_poll = "1" wgt_link = "1" wgt_featured-employee = "1" wgt_recent-content = "1" wgt_featured-article = "1" wgt_portal-update = "1" wgt_group-resource = "1" wgt_ads = "1" wgt_reminder = "1" wgt_suggested-content = "1" wgt_my-profile = "1" wgt_stock-ticker = "1"
Note: All widget names are prefixed with a 'wgt_'. Also note that to disable a widget,set the value to zero.
At this point, Precurio knows there is a stock-ticker widget, so it will look for a [stock-ticker] section which should contain important configuration information about the widget.
So the next step will be to include a [stock-ticker] section
[stock-ticker] stock-ticker.title = "Stock Ticker" stock-ticker.short_title = "Stock Ticker" stock-ticker.description = "This widget gives you near real-time information about your stocks. Results are delayed upto 20 minutes" stock-ticker.is_standalone = "0" stock-ticker.is_widget = "1" stock-ticker.position = "side" stock-ticker.order = "3"
Some explanation
- title : This is the name of the widget
- short_title : If the widget has a very long name, this should contain a shorter form of the name.
- description : This is a description for the widget. A good description helps the user know what the widget is all about
- is_standalone: This determines if the widget can also function as a standalone module, in most cases, this is "0" (i.e. false) for widgets.
- is_widget : This determines if it can function as a widget. This is always "1" (i.e. true) for widgets.
(is_widget and is_standalone may seem redundant, but you have to note that modules also use the same configuration. consider the [contact] section.)
- position : This is the default position you want the widget to take. Possible positions are "top","bottom","left","right","side". (see screenshot below)
- order : This is the order of the widget in its position. for example, our Stock Ticker widget will be the 3rd widget on the side bar.
After inserting the [stock-ticker] section, save the configuration file and go to user settings. The Stock Ticker widget should appear at the bottom of the widget list (also called start page pods or dashboard tools)
You will notice our new widget has a gear-like icon, this is the default icon for all widgets. Don't worry, we will look at how to set a more intuitive icon for our widget later.
Anyway, check (enable) the stock ticker widget, and click the update button. Then go to the home page (dashboard), and check the side position.
Viola!!!, the Stock Ticker widget now appears on the dashboard
Referencing Images/Icons
You may not immediately notice, but the delete icon is missing on the Stock Ticker widget.
Every theme and its containing style(s) has an "images" and "icons" folder that should contain application images and icons respectively. To make our delete icon appear, we just need to copy it into the "icons" folder of our current theme style.
My current theme is "insomnia", and it has only one style "blue", so i copy 'delete.png' to 'precurio/public/library/css/insomnia/blue/images/icons/' (you will notice the delete icon actually exists already. This is because it "delete" is a very popular action and so an icon will most likely already exist for it. Same goes for "add", "edit".)
After copying the icon, i change every occurrence of
<img src="delete.png" width="16" height="16" class="del"/>
to
<img src="http://localhost/precurio/public/library/css/insomnia/blue/images/icons/delete.png" width="16" height="16" class="del"/>
Save and refresh the home page, and the delete icon should appear.
Now there are two problem with this image reference
- It is too dependent on my own enviroment. it will only work locally on any machine where apache is listening on the default port 80.
- It will not work if the user does not have the insomnia theme.
Luckily we can easily fix this.
To fix problem 1, simply replace 'http: //localhost/precurio/public/' with "<?php echo $this->baseUrl();?>" To fix problem 2, we use property $this->themestyle. I.e. we replace "insomnia/blue" with "<?php echo $this->themestyle;?>"
So
<img src="http://localhost/precurio/public/library/css/insomnia/blue/images/icons/delete.png" width="16" height="16" class="del"/>
becomes
<img src="<?php echo $this->baseUrl();?>/library/css/<?php echo $this->themestyle;?>/images/icons/delete.png" width="16" height="16" class="del"/>
which will work fine in any enviroment and on any theme.
Setting the widget icon
Earlier, we noticed that our Stock Ticker widget took on the default widget icon which is a boring gear-like icon. To make our widget stand out from the pack, we need to give it a more intuitive icon.
Setting an icon for a widget is very easy, simply copy a 'png' file with the same name as the widget to the icons folder of the theme style.(The icon file name must follow the same rules as the folder view name, i.e. multiple words must be seperated by an hyphen, e.g. stock-ticker.png)
Once we copy stock-ticker.png to "\precurio\public\library\css\insomnia\blue\images\icons", the icon is immediately used as the widgets icon.
If you are using a theme style other than insomnia blue, you will have to copy the icon to the appropriate folder. Later on we will look at how to package our widget so that the icon file gets copied into all theme styles.
The Model
In an MVC framwework, the Model deals with the application logic, it is responsible for making the application 'work'.
Though am going to be using OOP concepts and the Zend framework/library in my model, but in practice, you can actually go about making your widget 'work' in anyway you find comfortable, be it writing all your application logic procedually in the view using raw PHP or using some other external library.
Before going on, let's re-iterate our planned features for the Stock Ticker widget;
- Display the current price of list of user selected stocks
- User should be able to add and remove a stock (portfolio)
- To add a stock, user can search for stock symbol by entering part of the stock name (e.g. a search for "microsoft" will return "MSFT" )
Below is the skeleton for my model, StockTicker.php, located in "\precurio\application\widget\models\".
class StockTicker{/*** Gets all the stocks for a specified user* @param int $user_id - optional (defaults to the current user)* @return Zend_Db_Table_Rowset*/static function getAll($user_id=0)
{}/*** Inserts default stocks for a user. This way, the stock ticker is never empty.* @param int $user_id - optional (defaults to the current user)* @return null*/static function insertDefault($user_id=0)
{}/*** Adds a new stock for the specified user* @param string $stock_symbol - Symbol of the stock, e.g. MSFT* @param string $stock_name - Name of the stock e.g. Microsoft Corporation* @param int $user_id - optional (defaults to the current user)* @return int - Primary key of the new stock.*/static function addNew($stock_symbol,$stock_name,$user_id=0)
{}/*** Deletes a particular stock from the user's stock list* @param string $stock_symbol* @param int $user_id - optional (defaults to the current user)*/static function deleteStock($stock_symbol,$user_id=0)
{}/*** Finds a stock using an internet service* @param string $search - search parameter* @return array*/static function findStock($search)
{}}
The StockTicker.php file also contains another class Stock, the represents an individual stock.
class Stock extends Zend_Db_Table_Row_Abstract
{/*** Gets stock data from internet service.*/public function getData()
{}public function getSymbol()
{}/*** Gets an id suitable for use, from the symbol.* This id is used in identifying html components*/public function getId()
{}public function getName()
{}public function getPrice()
{}public function getChange()
{}public function getPercentChange()
{}}
The implementation details are not the concern of this guide, you can review my source code if you are interested in implementing it my way.
The Database
Our Stock Ticker widget will definitely need a backend system to store the user selected stocks.
The diagram above shows the database schema am going to use. You can download the sql file here
Packaging the Widget
At this point, we have gotten our widget working to satisfaction, now it is time to package it for distribution.
It is advisable you read the Packaging Plugins for Precurio page before proceeding.
- The first step in packaging is to create my package folder. Which I will call "stock-ticker".
- Next, I create a subfolder "a". Subfolder "a" will contain 'StockTickerController.php' that will be copied to the '/application/widget/controllers/' directory of a Precurio installation.
- I create another subfolder "b". Subfolder "b" will contain 'StockTicker.php' that will be copied to '/application/widget/models/' directory of a Precurio installation
- I create another subfolder "c". Subfolder "c" will contain a 'stock-ticker' folder which contains the views for our widget, this folder will be copied to the '/application/widget/views/scripts/' directory of a Precurio installation.
- I create another subfolder "icons" that will contain the icons used while developing the widget. The subfolder "icons" will only contain file 'stock-ticker.png' since 'delete.png' already exists in all theme styles.
- I also copy our sql file that contains the "CREATE TABLE" sql command. This file will be executed by the Precurio Upgrade utility while installing the widget.
- I am also nice enough to put in a read me file, (which funny enough, should never get read under normal circumstances. You should also copy the readme file into all your widgets package.)
- I insert my instructions file 'upgrade.bat' that tell Precurio how to go about installing the widget.
The instruction file contains the following instructions (please read Packaging Plugins for Precurio to better understand this).
copy,/a/,/application/widget/controllers/; copy,/b/,/application/widget/models/; copy,/c/,/application/widget/views/scripts/; copyicons,/icons/; execute,wgt_stock_ticker.sql; set,wgt_stock-ticker,1,widget; set,stock-ticker.stock-ticker.title,Stock Ticker; set,stock-ticker.stock-ticker.short_title,Stock Ticker; set,stock-ticker.stock-ticker.description,This widget gives you near real-time information about your stocks. Results are delayed upto 10 minutes; set,stock-ticker.stock-ticker.is_standalone,0; set,stock-ticker.stock-ticker.is_widget,1; set,stock-ticker.stock-ticker.position,side; set,stock-ticker.stock-ticker.order,3;
- Finally, I zip the package folder to get my widget package file 'stock-ticker.zip', which you can download here.
Conclusion
Well, this brings us to the end of the widget development guide and I sincerely hope you have been able to follow through. If there is something that could have been better explained or you noticed a grammer error, please feel free to edit it, that's why we made the guide into a wiki instead of some pdf.
If you need further explanations/clarifications concerning this guide, please let's discuss it on our Extending Precurio forum.
For those itching to get started with Precurio Widget application, how about developing a Twitter Client widget, or a World Clock widget :)





