GTD Tools - AllMyThingsTodo

May 19, 2008

AllMyThingsToDo - Projects now ordered

Filed under: Uncategorized — admin @ 9:00 pm

Hi all.

Now the projects can be ordered the way you want, using the “order” field in each project.

The default value is 1000, and all the same priority projects are alphabetically ordered, as usual.

AND the “-1″ value hides the project from the main view and the project selector (to add new tasks).

Total programming time: 2 hours, I love cake php !!

April 5, 2008

Adding a CSV Export Feature

Filed under: cakephp — Tags: , , — admin @ 12:32 pm

Hi All:

This is a mini-howto to add a simple “export to csv” feature, so you can control your tasks and projects inside excel, or build reports of what you’ve done for a group of projects.

All the filters apply before the CSV file is created.

Note: The link to build the CSV is located at the bottom of the Tasks table.

Step by step tutorial:

  • Download this helper code. Note: the original code was posted by Adam Royle here i’m just copying his code for PHP 4 & 5:
<?php/*** CSV helper for cakePHP. Compatible with version 1.1.x.x and higher.*

* PHP versions 4 and 5

*

* Licensed under The MIT License

*

* @copyright		Adam Royle

* @license			http://www.opensource.org/licenses/mit-license.php The MIT License

*/

class CsvHelper extends Helper {	var $delimiter = ',';

var $enclosure = '"';

var $filename = null;

var $line = array();

var $buffer;

/**

* This option preserves leading zeros on numeric data when opened in Excel.

* Use it ONLY when the csv file is going to be opened in Excel, as it uses

* non-standard syntax, and will probably break in other systems.

*/

var $preserveLeadingZerosInExcel = false;

var $_tmpFile = false;

function CsvHelper() {

$this->clear();

}

/**

* Adds a multi-dimensional array to the buffer.

*

* @param array $data Multi-dimensional array

* @param boolean $addFieldNames Add a row of field names before adding data

* @access public

*/

function addGrid($data, $addFieldNames = true, $fieldList = null) {

if (!$data) {

return false;

}

if (@is_array(reset($row = reset($data)))) {

// Array generated by cakePHP model

// eg.

// $data = array(array('Model' => array('field_name' => 'field value')), array('Model' => array('field_name' => 'field value')))

$defaultModel = key($row);

if ($this->filename === null) {

$this->setFilename(Inflector::pluralize($defaultModel));

}

if ($fieldList) {

$fields = array();

foreach ($fieldList as $fieldName) {

if (strpos($fieldName, '.')) {

list($modelName, $fieldName) = explode('.', $fieldName);

} else {

$modelName = $defaultModel;

}

$fields[] = array(Inflector::humanize($modelName), $fieldName);

}

if ($addFieldNames){

foreach ($fields as $field) {

if ($field[0] != $defaultModel) {

$this->addField($field[0].’ ‘.Inflector::humanize($field[1]));

} else {

$this->addField(Inflector::humanize($field[1]));

}

}

$this->endRow();

}

foreach ($data as $row) {

foreach ($fields as $field) {

@$this->addField($row[$field[0]][$field[1]]);

}

$this->endRow();

}

} else {

if ($addFieldNames){

foreach (reset($row) as $key => $value) {

$this->addField(Inflector::humanize($key));

}

$this->endRow();

}

foreach ($data as $row) {

$this->addRow($row[$defaultModel]);

}

}

} else {

// Regular 2-dimensional array (with or without keys).

// eg.

//			$data = array(array(’field_name’ => ‘field_value’), array(’field_name’ => ‘field_value’))

//	or

//			$data = array(array(’field value’), array(’field value’))

if ($fieldList) {

if ($addFieldNames){

foreach ($fieldList as $fieldName) {

$this->addField(Inflector::humanize($fieldName));

}

$this->endRow();

}

foreach ($data as $row) {

foreach ($fieldList as $fieldName) {

@$this->addField($row[$fieldName]);

}

$this->endRow();

}

} else {

if ($addFieldNames) {

foreach (reset($data) as $key => $value) {

$this->addField(Inflector::humanize($key));

}

$this->endRow();

}

foreach ($data as $row) {

$this->addRow($row);

}

}

}

}

/**

* Adds a single field value to the buffer. You must call $csv->endRow() to commit fields to the buffer.

*

* @param string $value Field value

* @access public

*/

function addField($value) {

$this->line[] = $value;

}

/**

* Commits the row of fields that were added by addField()

*

* @access public

*/

function endRow() {

$this->addRow($this->line);

$this->line = array();

}

/**

* Adds a single row to the buffer.

*

* @param array $row Data to be added

* @access public

*/

function addRow($row) {

if ($this->preserveLeadingZerosInExcel) {

// convert the number to a string formula

foreach ($row as $key => $value){

if (strlen($value) > 1 && $value[0] == ‘0′ && is_numeric($value)) {

$row[$key] = ‘=”‘.$value.’”‘;

}

}

}

fputcsv($this->buffer, $row, $this->delimiter, $this->enclosure);

}

/**

* Outputs headers

*

* @param string $filename Filename to save as

* @access public

*/

function renderHeaders($filename = null) {

if (is_string($filename)) {

$this->setFilename($filename);

}

if ($this->filename === null) {

$this->filename = ‘Data.csv’;

}

if ($this->filename) {

header(”Content-disposition:attachment;filename=”.$this->filename);

}

header(”Content-type:application/vnd.ms-excel”);

}

/**

* Sets the output filename. Automatically appends .csv if necessary.

*

* @param string $filename Filename to save as

* @access public

*/

function setFilename($filename) {

$this->filename = $filename;

if (strtolower(substr($this->filename, -4)) != ‘.csv’) {

$this->filename .= ‘.csv’;

}

}

/**

* Returns CSV string and clears internal buffer. Outputs headers() if necessary.

*

* @param mixed $outputHeaders Boolean to determine if should output headers, or a string to set the filename

* @param string $to_encoding Encoding to use

* @param string $from_encoding

* @return string String CSV formatted string

* @access public

*/

function render($outputHeaders = true, $to_encoding = null, $from_encoding = “auto”) {

if ($outputHeaders) {

if (is_string($outputHeaders)) {

$this->setFilename($outputHeaders);

}

$this->renderHeaders();

}

if ($this->_tmpFile) {

rewind($this->buffer);

$output = ”;

while (!feof($this->buffer)) {

$output .= fread($this->buffer, 8192);

}

fclose($this->buffer);

} else {

rewind($this->buffer);

$output = stream_get_contents($this->buffer);

}

// get around excel bug (http://support.microsoft.com/kb/323626/)

if (substr($output,0,2) == ‘ID’) {

$pos = strpos($output, $this->delimiter);

if ($pos === false) {

$pos = strpos($output, “\n”);

}

if ($pos !== false) {

$output = $this->enclosure . substr($output, 0, $pos) . $this->enclosure . substr($output, $pos);

}

}

if ($to_encoding) {

$output = mb_convert_encoding($output, $to_encoding, $from_encoding);

}

$this->clear();

return $this->output($output);

}

/**

* Clears internal buffer. This is called automatically by CsvHelper::render()

*

* @access public

*/

function clear() {

$this->line = array();

$this->buffer = @fopen(’php://temp/maxmemory:’.(5*1024*1024), ‘r+’);

if ($this->buffer === false) {

$this->_tmpFile = true;

$this->buffer = tmpfile();

}

}

}

/**

* A PHP4 implementation of the equivalent PHP5 function

*

* See (http://www.php.net/manual/en/function.fputcsv.php) for details

*/

if (!function_exists(’fputcsv’)) {

function fputcsv(&$handle, $fields = array(), $delimiter = ‘,’, $enclosure = ‘”‘) {

$str = ”;

$escape_char = ‘\\’;

foreach ($fields as $value) {

settype($value, ’string’);

if (strpos($value, $delimiter) !== false ||

strpos($value, $enclosure) !== false ||

strpos($value, “\n”) !== false ||

strpos($value, “\r”) !== false ||

strpos($value, “\t”) !== false ||

strpos($value, ‘ ‘) !== false) {

$str2 = $enclosure;

$escaped = 0;

$len = strlen($value);

for ($i=0;$i<$len;$i++) {

if ($value[$i] == $escape_char) {

$escaped = 1;

} else if (!$escaped && $value[$i] == $enclosure) {

$str2 .= $enclosure;

} else {

$escaped = 0;

}

$str2 .= $value[$i];

}

$str2 .= $enclosure;

$str .= $str2.$delimiter;

} else {

$str .= $value.$delimiter;

}

}

$str = substr($str,0,-1);

$str .= “\n”;

return fwrite($handle, $str);

}

}

?>
  • Copy this code into file /app/views/helpers/csv.php
  • Add the helper to the controller where you are planning to use the CSV export feature.

class XXXController extends AppController {
.....
var $helpers = array('Html', 'Form' , 'Javascript', 'Ajax', ‘Csv’);
.....

  • Create an export method that fetches the data (with a findAll for example) and set the data to the view. This method goes inside the controller with the CSV helper, of course :)

function exportcsv() {
$this->layout = '';
$this->set('dataToExport', $this->ZZZZ->findAll());

}

  • Now, create a file in /app/views/yourcontrollername/exportcsv.ctp with this contents

<?php
$csv->addGrid($
dataToExport);
echo $csv->render(true);
?>

  • Done !

Notes: If you want to test the code generated, change render(false) for render(true) on the view, and the code will be shown on the browser.

Enjoy this new feature.

March 20, 2008

CakePHP rss reader component installation

Filed under: cakephp — admin @ 1:23 pm

Hi all !

Today I’ve installed an RSS Reader Component in my cake application, so you can read the news at login time.

How ?

First, after searching cake community (bakery), I located this CakePHP RSS component

Following the instructions (very easy), you download the component into your vendors and components folder, then use it to get the feed, and display it as you like.

Tip: Cake has a funtion “truncate” inside the Text Helper to aid you if you like to get the first N characters for a headline or description of your feed.

Here is the code I’ve used

#CONTROLLER
var $helpers = array('Javascript','DAuth', 'Text');
var $components = array('DAuth','RequestHandler', 'Simplepie');
...... code ......
$items = $this->Simplepie->feed('http://blog.allmythingstodo.com/rss');
$this->set('feeds', $items);
#END OF CONTROLLER

#VIEW
<?php
foreach($feeds as $feed) {
  echo $html->link($feed->get_title(), $feed->get_permalink()) . '<br/>';
  echo $text->truncate($feed->get_description());
}
?>
#END OF VIEW

March 16, 2008

Hello !

Filed under: Uncategorized — admin @ 6:20 pm

Hello dear allmythingstodo user or casual reader.

My name is Mauro Cabestany and I’m working now for 3 months in this little project, which aims to be a complete GTD oriented Personal Management Tool, to assist you in your workload planning.

Please feel free to login at my GTD Tools - AllMyThingsToDo page and start using it for free.

By the way, don’t worry about your email, or use a junk email to register because we are not using any validation. If we need to contact you, we’ll use this blog to keep in touch with AMTTD users.

Remember, contribute with suggestions or comments. Positive and negative feedback is welcome.

Spammers, please don’t touch my blogs.

Powered by WordPress