jueves, 10 de marzo de 2011

Making IIS 7 serve MrSID Files

Until IIS 6 in order to serve MrSID files all you had to do was assign the proper NTFS permissions to the folder where the files were located and create a virtual directory in IIS. If you only do that and try to access a URL to an MrSID file on II 7 you´ll get a “404 - File or directory not found.” . The error message is confusing since the directory does exist. Finally figured there where restrictions with the MIME type, it seems IIS 7 only serves MIME you specifically declared.

To declare a new MIME type for MrSID you have to add an additional step.

1. Open the IIS Manager

2. Click on the virtual directory or directory

3. Click on MIME Types

4. Click on Add…

5. Fill the File name extension as .sid and the MIME type as application/octet-stream


6. Click Ok.

Now you should be able to access your MrSID via an URL.

martes, 8 de marzo de 2011

Using Pagination with Symfony and Doctrine 2

When I blogged Using Pagination with Symfony and Doctrine I had being trying to understand the inner working of the Symfony's Admin Generator. At the time it seem a good solution. But, when I started implementing the idea, I realized that I had to repeat very similar code on each of the of the actions of the modules I was working.
So I decided to try a different aproach. I put all de code I was using in the actions in a utility class, created a widget to render the header and added a partial to render how many items in the table and the total number of pages. The final goal was to create my first Symfony plugin, but I'm not quite there yet, so I decided to blog first this improvement.
The Pagination Control
Since it's the same control I proposed in my previous blog Using Pagination with Symfony and Doctrine I will not repeat the code. You still need to get the images for buttons and place them in your web\images folder.
The Pagination Info Control
Create a file named /myproject/apps/myapplication/templates/_pagination_info.php and copy the following code on it. Then save it.
<div class="pagination_info">
<?php echo format_number_choice('[0] no result|[1] 1 result|(1,+Inf] %1% results',
array('%1%' => $pager->getNbResults()), $pager->getNbResults(), 'sf_admin') ?>
<?php if ($pager->haveToPaginate()): ?>
<?php echo __('(page %%page%%/%%nb_pages%%)', array('%%page%%' => $pager->getPage(),
'%%nb_pages%%' => $pager->getLastPage()), 'sf_admin') ?>
<?php endif; ?>
</div>
Creating the Paging Utility
Create a file named /myproject/lib/model/PagingUtility.class.php and copy the following code on it. Then save it.
This class will take care of all the code previously had to copy into the actions.
class PagingUtility {
private $modelname;
private $sortkey;
private $user;
private $modulename;

public function __construct($modelname, $user) {
$this->modelname=$modelname;
$this->user =$user;
$this->sortkey =strtolower($this->modelname).".sort";
$this->modulename = strtolower($this->modelname) . "_module";
}

public function buildPager($request, $items_x_page,$query=NULL){
if ($request->getParameter('sort') && $this->isValidSortColumn(
$request->getParameter('sort'))) {
$this->setSort(array($request->getParameter('sort'),
$request->getParameter('sort_type')));
}

// $items_x_page = sfConfig::get('app_max_items_x_page');
$pager = new sfDoctrinePager($this->modelname, $items_x_page);
//$device = is_null($coffeeMaker) ? "hands" : $coffeeMaker;
$query = is_null($query) ? $this->buildQuery() : $query;
$pager->setQuery($query);
$pager->setPage($request->getParameter('page', 1));
$pager->init();
return $pager;
// $this->sort = $this->getSort();
}
protected function buildQuery() {
$et = Doctrine_Core::getTable($this->modelname);

$query = $et->createQuery();

$this->addSortQuery($query);

return $query;
}

protected function addSortQuery($query) {
if (array(null, null) == ($sort = $this->getSort())) {
return;
}

if (!in_array(strtolower($sort[1]), array('asc', 'desc'))) {
$sort[1] = 'asc';
}
$query->addOrderBy($sort[0] . ' ' . $sort[1]);
}

public function getSort() {
if (null !== $sort = $this->user->getAttribute($this->sortkey,
null, $this->modulename)) {
return $sort;
}

$this->setSort(array(null, null));

return $this->user->getAttribute($this->sortkey,
null, $this->modulename);
}

protected function setSort(array $sort) {
if (null !== $sort[0] && null === $sort[1]) {
$sort[1] = 'asc';
}
$this->user->setAttribute($this->sortkey, $sort, $this->modulename);
}

protected function isValidSortColumn($column) {
return Doctrine::getTable($this->modelname)->hasColumn($column);
}
}
Creating the Sortable Header Widget
I'm not sure if creating a widget for this purpose would be the best approach, but I wanted to make my own widget a see how it worked. The code is an adaption of the code from a previous blog entry Sorting Lists in Symfony.
Create a file named /myproject/lib/widget/maSortableHeader.php and copy the following code on it. Then save it.
class maSortableHeader extends sfWidgetForm {

protected function configure($options = array(), $attributes = array()) {
$this->addOption('fieldname');
$this->addOption('fieldlabel');
$this->addOption('routename');
$this->addOption('sort');
}

public function render($name, $value = null, $attributes = array(), $errors = array()) {
$sort = $this->getOption('sort');

if ($this->getOption('fieldname') == $sort[0]) {
$config = array('query_string' => 'sort=' . $this->getOption('fieldname') . '&sort_type=' .
($sort[1] == 'asc' ? 'desc' : 'asc'));
$uri = link_to($this->getOption('fieldlabel'), $this->getOption('routename'),
$config);
$uri .= image_tag('/images/' .
$sort[1] . '.png', array('alt' => $sort[1],
'title' => $sort[1]));
} else {
$uri = link_to($this->getOption('fieldlabel'), $this->getOption('routename'),
array('query_string' => 'sort=' . $this->getOption('fieldname') . '&sort_type=asc'));
}

return $uri;
//optional - for easy css styling
}

}
Editing the Action


On our action we're going to implement our PagingUtiliy and add widets for two columns (Code and Name). Our executeIndex function looks like this:
public function executeIndex(sfWebRequest $request)
{
$pu = new PagingUtility("Category", $this->getUser());
$items_x_page = sfConfig::get('app_max_items_x_page');
$this->pager = $pu->buildPager($request, $items_x_page);

$this->sort = $pu->getSort();

//Adding SortableHeaders
$this->form = new sfForm();
$this->form->setWidget('code_sorted',
new maSortableHeader(array('fieldname'=>'code',
'fieldlabel'=>'Code', 'routename'=>'@category','sort'=>$pu->getSort())));
$this->form->setWidget('name_sorted',
new maSortableHeader(array('fieldname'=>'Name',
'fieldlabel'=>'Name', 'routename'=>'@category','sort'=>$pu->getSort())));

}
You still need to get the asc.png and desc.png into your web/images folder for the widget to show icon besides the header.

Editing the indexSuccess.php
What we need to do now is show the Sortable Headers, change the default loop to use the pager, add the pagination control and the pagination info partials.
<thead>
<tr>
<th><?php echo $form['code_sorted']; ?></th>
<th><?php echo $form['name_sorted']; ?></th>
<th>Description</th>
<th>Created at</th>
<th>Updated at</th>
<th>Created by</th>
<th>Updated by</th>
</tr>
</thead>
<tbody>
<?php foreach ($pager->getResults() as $i => $category): ?>
<tr>
<td><a href="<?php echo url_for('category/edit?id='.$category->getId()) ?>"><?php echo $category->getCode() ?></a></td>
<td><?php echo $category->getName() ?></td>
<td><?php echo $category->getDescription() ?></td>
<td><?php echo $category->getCreatedAt() ?></td>
<td><?php echo $category->getUpdatedAt() ?></td>
<td><?php echo $category->getCreator() ?></td>
<td><?php echo $category->getUpdator() ?></td>
</tr>
<?php endforeach; ?>
</tbody>
<tfoot>
<tr>
<td colspan="7">
<?php include_partial('global/pagination_info', array('pager' => $pager)) ?>
<?php include_partial('global/pagination_control', array('pager' => $pager, 'module' => 'category')) ?>
</td>
</tr>

Editing the Routing.yml
This is the step I always forget. Mainly because I don't quite undertand what it does. I will look into it an post my findings. For now it will not work unless you add the follwing code to your routing.yml.
category:
class: sfDoctrineRouteCollection
options:
model: Category
module: category
prefix_path: /category
column: id
with_wildcard_routes: true

jueves, 3 de marzo de 2011

QR Codes a Cool Way to Share Data

I recently discovered QR Codes. QR Codes (QR is short for Quick Read) were created by Denso-Wave a subsidiary of Toyota. They are a type of barcode that can be read by both barcode readers and smartphones with cameras. This is my blogs url encoded in QR Code:

These codes are being used extensively in advertising and even in games. But the thing I like the most is there are several QR code generator online.

The jewel of the crown is that a QR Code are set down in the ISO-18004 standard so they are the same all over the world.

QR Code Online Generators

There are several online QR Code Generators. The followings are the ones I took a peek at:

  1. I found Kaywa QR Code to be very good.

  2. QR Code Generator from the ZXing Project: Is based on the Googles Chart API and has more types of contents for example has a WIFI Network format. It also has a geo location format which is great.

    This the URL for the Biodiversity Museum in Panama.
  3. QRStuff : has more data types than XZing Project but my QR reader doesn't work with all of them. I create a QR a code for an email message and even though the reader read it, I got an error when I tried to send the email. I like this QR generator site because it has a lot of information on QR codes.
Now if you're sort of a nerd (like me) you are probable thinking how to embed the online creators into your own application. The coolest thing about QR codes it's that they are supported the Google Chart API. For example to create a QR code to encode the phrase Hola Panama (Hello Panama) all you have to do is build an URL like this one:

http://chart.apis.google.com/chart?cht=qr&chs=350x350&chl=Hola+Panama

You'll get a QR code like this


QR Code Reader

Since I have Blackberry I just focused on readers for BBs. But you can find readers for iPhone, Android and certain versions of Nokias OSs. I found a list of barcode readers can be found at http://www.mobile-barcodes.com/qr-code-software/blackberry/.
I chose i-nigma only because it supported many other phones aside from Blackberry. Once installed it has been working great.