Showing posts with label php. Show all posts
Showing posts with label php. Show all posts

Monday, March 21, 2011

XDebugButton. Php XDebug with Vim.

Vim is fucking awesome. Vim is fucking extensible.
You may find a lot of plugins transforming it in a perfect IDE for you programming language.
One of the best plugin for php programmers is xdebug, which runs a debug session right into vim.
On the web you may find many articles, explaining how-to install it and make it working (it involves some configurations in vim, php.ini), here is the one I read.
Once you have installed it and made it working, you'll know that to activate the connection between vim and the server you have to recharge the web page passing a get variable: XDEBUG_SESSION_START=1
Now here comes my work, very easy indeed, but was my first firefox addon developement.
I wrote a firefox extension that appends automatically the paramether at  the url, checking for the right symbol to insert (& or ?).
You may find my addon source, with the instructions on how-to install it on my github account here.
From command line you may simply clone my project (install git first)
git clone git://github.com/abidibo/XDebug-Button---Firefox-Add-on.git
If you find errors or bugs please write to abidibo@gmail.com.

Friday, March 4, 2011

Add total time logged in infos to SMF message posters

Well,
some hours ago I had the need to show the total time logged in info in the poster message area below the number of posts published by the member.
The forum platform is SMF, I 've just started working with it so I can't give a professional opinion about it.
Now what we have to do to achieve our goal is what follows.
  1. Edit the /Sources/Load.php file.
    goto line 838 (inside the loadMemberData method) and add to the fields selected by the query the one we want: mem.totalTimeLoggedIn
  2. Well, now the information we want is selected from db.
  3. Goto line 1006 (inside loadMemberContext method). Here the member context variable to be passed to the template is prepared. We have to add our informations to the array returned by this method, so add the following key=>value pair to the $memberContext[$user]  array:
    'total_time_logged_in' => array(
    'days' => floor($profile['totalTimeLoggedIn'] / 86400),
    'hours' => floor(($profile['totalTimeLoggedIn'] % 86400) / 3600),
    'minutes' => floor(($profile['totalTimeLoggedIn'] % 3600) / 60)
    )
  4. Well done, now our information is present in the context member variable passed to the template we have to edit. Notice that we have divided the amount of time in days, hours and minutes.
  5. Now we have to show this information in the right place, that is the right template, which is /Themes/default/Display.template.php, or the one corresponding to your used theme if present in the theme folder. Open the file and goto line 316. At this line are printed the informations about the number of posts written by the message poster, so below that we insert our code:
    // Show how many posts they have made.
    echo '
    ', $txt[26], ': ', $message['member']['posts'], '

    ';
    // Show total time online.
    if (!empty($message['member']['total_time_logged_in'])) {
    echo '
    ', $txt['totalTimeLogged1'];

    // If days is just zero, don't bother to show it.
    if ($message['member']['total_time_logged_in']['days'] > 0)
    echo $message['member']['total_time_logged_in']['days'], $txt['totalTimeLogged5'];

    // Same with hours - only show it if it's above zero.
    if ($message['member']['total_time_logged_in']['hours'] > 0)
    echo $message['member']['total_time_logged_in']['hours'], $txt['totalTimeLogged6'];

    // But, let's always show minutes - Time wasted here: 0 minutes ;).
    echo $message['member']['total_time_logged_in']['minutes'], $txt['totalTimeLogged7'], '<br /><br />';
    }
    else echo '<br />';
Ok, only some considerations:
I displayed the count of time in this form;
xd xh xm
you can show it as
x days x hours and x minutes
or in the form you want, you only have to edit the language locate files of the languages you're interedsted in and set the text you prefer, you may define new strings and so on. Brutally you may also print the string you want directly into the template without using the locate system.
Hasta la proxima siempre.

Wednesday, July 28, 2010

HowTo navigate through a tree without recursive methods (while loop instead)

-Hi,
today I was simply writing a local template in order to render a menu following the MVC pattern.
Now my local template system does not use a meta-language, but loops, if statements and so on are written directly in php, because I don't have enough time to write an interpreter.
So really I can use all php functionalities in my templates including recursive functions. But it's not the way I want to follow, moreover maybe some day I'll find the time to write my interpreter and then will be very easy to "convert" if statements and cycles, not so easy if not impossible to convert recursive functions.
Well, so the problem was the following:
I have a n-dimensional menu tree, and have to generate the classical html code for such a menu, that is something like:
<ul id="nav">
    <li>Voice1</li>
    <li>Voice2
        <ul>
            <li>Voice21</li>
            <li>Voice22</li>
        </ul>
    </li>
    <li>Voice3</li>
</ul>
So let's see HOW TO get this without recursion. The code is well commented, here it goes:
<?php

/*
 * Menu tree is represented by an n-dimensional array.
 * Array keys are the labels and array values are either a link
 * or a submenu (another array)
 */
$voices["Home"] = array("Home1" => array("Home11"=>"#"), "Home2"=>array("Home21"=>"#"));
$voices["News"] = array("News1" => "#", "News2"=>array("News21"=>"#"));
$voices[_("About")] = array("About1"=>array("About11"=>array("About111"=>"#", "About112"=>"#")), "About2"=>"#");
$voices[_("Services")] = '#';
$voices[_("Faq")] = '#';

/*
 *  INIT SOME VARIABLES
 */
// control the exit from the loop
$continue = true;
// this variables stores the branch currently analized
$parsed = $voices;         
// stores all the branches parsered, because the tree is navigated following a branch
// until the foil. So when returning on top levels the navigation must continue on
// branches interrupted earlier.
$tree = array();
// stores the last key of the current branch array
$last = null;

echo "<ul id=\"nav\">\n";

/*
 *  THE MAIN LOOP
 */
while($continue === true) {
    // if the value of the current element parsered is an array than has a submenu
    if(is_array(current($parsed))) {
        // echo the current voice and open a new submenu (ul)
        echo "<li><a href=\"#\">".key($parsed)."</a>\n<ul>\n";
        // we're going to begin navigate the branch ->
        // we store the branch we're leaving in the tree array
        $tree[] = $parsed;
        // the branch to analyze is now the submenu
        $parsed = current($parsed);
        // get the last key of the new branch
        end($parsed);
        $last = key($parsed);
        // reset the array pointer
        reset($parsed);
    }
    // else if the value of the current element is not an array (but a link)
    // and not false (i.e. after calling next on the last element of an array)
    elseif(current($parsed)!==false) {
        // echo the current voice
        echo "<li><a href=\"".current($parsed)."\">".key($parsed)."</a></li>\n";

        // if the voice printed is the last of its branch
        // than close the submenu and get the last branch stored in the
        // varable tree (the parent branch) as the one to follow parsering
        if(key($parsed)==$last) {
            echo "</ul></li>\n";
            $parsed = array_pop($tree);
        }
        // move the pointer to the next element
        next($parsed);
    }  
    // else the value of the current element is false -> we have already passed the last element
    // then we close the submenu and get the parent branch as the current one, passing to the next element
    else {
        echo "</ul></li>";
        $parsed = array_pop($tree);
        next($parsed);
    }

    // if we are navigating the first tree level and have passed through all them -> exit
    if(count($tree)==0 && current($parsed)==false) $continue = false;
}

echo "</ul>\n";
?>
Hasta la proxima!

Friday, July 9, 2010

Get MySQL table data structure with PHP

Hi, today I'll show how to retrieve informations about a MySQL table through php in order for example to create a php class making editable a table in an automatic way (that is: stupid class, i give you a name of a table and YOU have to create its backend for me). This work is done very well by the python framework Django for example.
Now, there are several ways to do so, I'll use the interrogation of the information_schema db.
Well, let's see the code. I post here a simple function, clearly the informations that may be retrieved are more than these.
function getTableStructure($dbname, $table) {
    $structure = array();
    $fields = array();

    $query = "SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '$dbname' AND TABLE_NAME = '$table'";
    $res = mysql_query($query);

    while($row = mysql_fetch_array($res)) {
        $fields[$row['COLUMN_NAME']] = array(
            "order"=>$row['ORDINAL_POSITION'],
            "default"=>$row['COLUMN_DEFAULT'],
            "null"=>$row['IS_NULLABLE'],
            "type"=>$row['DATA_TYPE'],
            "max_length"=>$row['CHARACTER_MAXIMUM_LENGTH'],
            "key"=>$row['COLUMN_KEY'],
            "extra"=>$row['EXTRA']
        );
        if($row['COLUMN_KEY']=='PRI') $structure['primary_key'] = $row['COLUMN_NAME'];
    }
    $structure['fields'] = $fields;

    return $structure;

}

The important informations to do an auto-generation-form class are:
  • default: the default value (we may insert it as a default value in the input field of the form)
  • null: we may use it to decide whether a field must be compulsory or not
  • type: the must important: which form element we'll use? It depends on data type and ...
  • max_length: the maximum number of characters acceopted for the field
  • key: we may want to check for uniques keys etc...
  • extra: i think it's useful to know if a field is auto_increment because we may not make it editable
That's all falks, hasta la proxima!

Thursday, October 8, 2009

Tables using FPDF Library

Hi!
This time we'll speak about the exportation of tables in pdf format. I needed a way to print some dockets regarding persons data. This dockets have to be printed using special paper, that is that paper which already have the dockets ready and cut. So the goal of my work was to found a way to generate a table with perfectly equal cells of a given width and height. These cells must contain some text, which is not fixed, but may contain different informations:
Surname - name, Company (optional), Address (may stay on 2 lines), CAP City.
Why didn't I use html and the javascript print function to make it work? Clear, because I was glad to study something new and because printing to a pdf file is a more professional way to solve this problem.
One difficulty was represented by the variability of the text, so I assumed that each cell could have a maximum of 5 lines:
- surname and name
- company (optional)
- address 1 line
- address 2 line (if needed)
- cap and city
So there can be dockets containing text between 3 an 5 lines.
I decided to use the fpdf library which is free of course. You may download it from here (I used the last version 1.6).
Now this library has many useful functions but I extended it in order to get my desired table.
So here is my class and below how to instanciate and use it. Good reading.
<?php
/*
 * CLASS TblFPDF
 * 08/09/2009
 * written by abidibo <abidibo@gmail.com>
 * Copyright: FUCK COPYRIGHT, NO LICENCE TAKE THIS CODE AND DO WHAT YOU WANT
 *
 * Description
 *     This class allows to create a pdf table made by cells all of the same dimensions
 *     (width and height) and containing some text. This text must follow some rules, as
 *     this class was written in order to print some dockets, and dockets hava a fixed
 *     structure. More informations later.
 *
 * Parameters of __construct function
 *      (int) $nRows : number or rows for document page
 *      (int) $nCols : number of columns
 *      (float) $cellWidth : width of every single cell in mm
 *      (float) $cellHeight : height of every single cell in mm
 *      (mix) $cellBorder : cell border property
 *               0 -> no border
 *               1 -> border
 *               string containing one ore more characters:
 *               L -> left border
 *               T -> top border
 *               R -> right border
 *               B -> bottom border
 *
 * Parameters of render function
 *     (array) $textArray : an array where each element represent the string
 *                          to insert in a cell. Break lines represented by \n
 *     (int) $cellLines : the maximum number of lines inside a cell.
 *
 *     The $textArray[$i] text foreach $i has to stay inside the cell, that is has to have
 *     a maximum of ($cellLines-1) break lines or less if the text between two
 *     break lines is so long that can't stay in a single line of width $cellWidth.
 *     That's a very important condition!
 *
 */

// include fpdf library and set the constant it used to charge font folder
// font folder is given with the library
define('FPDF_FONTPATH',dirname(__FILE__).'/font/');
require('fpdf.php');

class TblFPDF extends FPDF {
    function __construct($nRows, $nCols, $cellWidth, $cellHeight, $cellBorder) {
 
        parent::__construct();
        $this->_nrows = $nRows;           // rows for page
        $this->_ncols = $nCols;           // columns
        $this->_cellw = $cellWidth;
        $this->_cellh = $cellHeight;
        $this->_cellb = $cellBorder;
    }

    public function render($textArray, $cellLines) {

        $count = 0;
        reset($textArray);
        $totCell = count($textArray);
        $totPages = ceil($totCell/($this->_nrows*$this->_ncols));
      
        for($p=0;$p<$totPages;$p++) {
            $this->AddPage();
            for($r=0;$r<$this->_nrows;$r++) {
                for($c=0;$c<$this->_ncols;$c++) {
                    if($count>=$totCell) break;       // all cells has been already printed
                    $this->setXY($c*$this->_cellw, $r*$this->_cellh);    // set x and y position of the top left corner of the new cell
                    $this->renderCell(current($textArray), $cellLines);
                    next($textArray);
                    $count++;
                }
            }
        }
    }

    private function renderCell($text, $cellLines) {

        $totLines = 0;
        $text_lines = explode("\n", $text);
        for($i=0;$i<count($text_lines);$i++) {
            $totLines++;
            if($this->getStringWidth($text_lines[$i])>=$this->_cellw-2.6) $totLines++;
        }
        if($totLines<$cellLines) $text .= "\n";
        for($i=0;$i<($cellLines-$totLines);$i++) $text .= "\n";

        $this->MultiCell($this->_cellw, ($this->_cellh/$cellLines), $text, $this->_cellb, "L");
    }
}
?>

So this was the class I used. It's well commented, but let's see how to use it

<?php

require_once(class.TblFPDF.php);

$textArray = array(
                          0=>"Name Surname\nCompany\nAddress\nCAP City",
                          1=>"Gino Pinotto\nTalisker spa\n5th 23/q\n10384 New York"
                      );
$pdfDoc = new TblFPDF(8,3,70,37,1);
$pdfDoc->render($textArray);
$pdfDoc->Output();
exit();

?>

In this example the output will be a pdf document with two dockets drawned starting from the point (0,0) of the page, containing the informations included in $textArray. If many text elements are given the full page will have 8 rows for 3 columns, each cell will have a width of 7 cm and an height of 3.7 cm, with a black border. The text inside the cell must occupy not more than 5 lines, that's the only recomendation.
Hope is useful.
Bye!
PS. Yesterday Italy's top court stripped Mr. Berlusconi of his legal immnuity (I gloat for this), hoping justice may be done I'll have a great party!