GIS books from ESRI

And a lot of other ESRI books.

ebook - GIS in Africa

Posted in ebook, geo | Leave a comment

new Carto magazine, #3

Released the new issue of Carto magazine, #3 December 2010 – January 2011:

Posted in geo | Leave a comment

mediawiki leaves beta behind: v1.16.0 update

Some ten days ago, Mediawiki released finally the 1.16 version withouth the “beta” surname.

We are proud to announce the first stable release of the 1.16 series.
Selected changes that may be of interest since MediaWiki 1.15 are:

  • Watchlists now have RSS/Atom feeds. RSS feeds generally are now hidden, since Atom is a better protocol and is supported by virtually all clients.
  • It’s now possible to block users from sending email via Special:Emailuser.
  • The maintenance script system was overhauled. Most maintenance scripts now have a useful help page when you run them with –help.
  • AdminSettings.php is no longer required in order to run maintenance scripts. You can just set $wgDBadminuser and $wgDBadminpassword in your LocalSettings.php instead.
  • The preferences system was overhauled. Preferences are stored in a more compact format. Changes to site default preferences will automatically affect all users who have not chosen a different preference.
  • Support for SQLite was improved. Some broken features were fixed, and it now has an efficient full-text search.
  • The user groups ACL system was improved by allowing rights to be revoked, instead of just granted.
  • A new localisation caching system was introduced, which will make MediaWiki faster for almost everyone, especially when lots of extensions are enabled.

By default, this new system makes a lot of database queries. If your database is particularly slow, or if your system administrator limits your query count, or if you want to squeeze as much performance as possible out of Mediawiki, set $wgCacheDirectory to a writable path on the local filesystem. Make sure you have the DBA extension for PHP installed, this will improve performance further.

There were also some other security issues fixed that you can read in the mediawiki release note.

Major vs minor mediawiki upgrade

As it was a minor upgrade, only files were affected. Major upgrades can (and usually do) affect the database, and they change the second number in version: 1.15 to 1.16 for example. Minor upgrades do not affect the database, only files, and they change the third number in version: 1.15.4 to 1.15.5, or 1.16.0beta3 to 1.16.0, as this is the case.

Files affected are:


/CREDITS
/RELEASE-NOTES
/languages/Classes/* (more than half of the files)
/maintenance/Mantenance.php
/maintenance/language/messages.inc
/maintenance/ora/tables.sql
/maintenance/tests/MediaWikiParserTest.php
/skins/common/jquery.js
/skins/common/jquery.min.js
/skins/common/wikibits.js
/skins/vector/experiments/* (4 css files)
/skins/vector/experiments/images/* (11 png files)

And there are two other files updated in the 1.16 version, but they are not important as they only rename some divs:


/skins/Vector.php
/skins/vector/main-ltr.css

I have installed new versions in wikiprogress (1.16.0) and wikigender (1.15.5), and they work perfectly:



Posted in mediawiki | Leave a comment

Toast – unit testing for codeigniter http://jensroland.com/projects/toast/

Posted on by fulgen | Leave a comment

awesome examples of maps & infographics http://ht.ly/2j3R3http://ht.ly/2j3Tchttp://ht.ly/2j40p

Posted on by fulgen | Leave a comment

mediawiki news, aka recent changes

The mediawiki tecentchanges special page

The list of changes in mediawiki is presented in a SpecialPage called Recentchanges, quite extensive and useful:

The problem is, when including this page on another, it is showed like this:


Which looks awful, with all wiki codes like == or {{, or html codes like
. Isn’t there a better solution than modifying a special page (which would be overwritten with an upgrade)?

The wikihow model

Wikihow created a very nice approach to this:


As far as I can see, it lists these types of changes:

  • a new user joined the wiki;
  • a new file uploaded;
  • a category added to an article;
  • an edition to an article;
  • a user left a message to another;
  • and of course, when a new article is created.

Except for the user messaging system, which is probably based on a specific extension, all the others can be taken from the database. Also, the category addition is not that different from an article edition, so I will leave that one apart too.

recent changes sql, the core

There are four key data items to get for each news:

  • what it is about (joining, creating, editing, uploading);
  • when it occurred (here it comes handy the date semantics function);
  • who did it (the user);
  • and where happened (the link with further info).

What, when, who and where sounds like a good plan. Let’s see the queries:

a new user joined the wiki

The query is quite easy, new users are those who registered last:

SELECT user_id, user_name, user_registration, "joined", CONCAT("User:", user_name)
FROM user
ORDER BY user_registration DESC

an article was created

This query is probably the most complicated, as it comes from the most important couple of tables in mediawiki, revisions and pages.

Basically, it takes all changes if they had some content (length > 0), if they are new pages (‘Created…’), and only from proper content pages (i.e., not talk pages or special content, that is, namespace = 0):

SELECT r.rev_user, r.rev_user_text, r.rev_timestamp, "created", r.rev_page, p.page_title
FROM `revision` r, page p
WHERE r.rev_page = p.page_id
  AND r.rev_len > 0
  AND r.rev_comment LIKE 'Created%'
  AND p.page_namespace = 0
ORDER BY rev_timestamp DESC

an article was edited

Same as above, changing the comment; since there can be several changes for the same page, we take the latest only:

SELECT r.rev_user, r.rev_user_text, max( r.rev_timestamp ), "edited",  r.rev_page, p.page_title
FROM `revision` r, page p
WHERE r.rev_page = p.page_id
  AND r.rev_len > 0
  AND  r.rev_comment NOT LIKE 'Created%'
  AND p.page_namespace = 0
GROUP BY r.rev_user, r.rev_user_text, r.rev_page, p.page_title
ORDER BY 3 DESC

This query can be improved, depending on each use: not listing sysops editions, or those on the home page. May you have a special need for these, please leave a comment below.

a file was uploaded

Quite easy, after the previous queries:

SELECT i.img_user, i.img_user_text, i.img_timestamp, "uploaded", p.page_id, i.img_name
FROM image i, page p
WHERE p.page_title = i.img_name
ORDER BY img_timestamp DESC

The final query, putting it all together

Every query has different columns, different column names and maybe even types, so they must be unified, and joined through a UNION clause. Also, the ORDER BY must be the same for all.

(SELECT user_id, user_name, user_registration AS d_when, "joined" AS what, 0 AS page_id, CONCAT("User:", user_name) AS page_title FROM user)
UNION
(SELECT r.rev_user AS user_id, r.rev_user_text AS user_name, max( r.rev_timestamp ) AS d_when, "edited" AS what,  r.rev_page AS page_id, p.page_title FROM `revision` r, page p WHERE r.rev_page = p.page_id AND r.rev_len > 0 AND r.rev_comment = "" AND p.page_namespace = 0 GROUP BY r.rev_user, r.rev_user_text, r.rev_page, p.page_title )
UNION
(SELECT r.rev_user AS user_id, r.rev_user_text AS user_name, r.rev_timestamp AS d_when, "created" AS what, r.rev_page AS page_id, p.page_title FROM `revision` r, page p WHERE r.rev_page = p.page_id AND r.rev_len > 0 AND r.rev_comment LIKE 'Created%' AND p.page_namespace = 0 )
UNION
(SELECT i.img_user AS user_id, i.img_user_text AS user_name, i.img_timestamp AS d_when, "uploaded" AS what, p.page_id, i.img_name AS page_title FROM image i, page p WHERE p.page_title = i.img_name)
ORDER BY d_when DESC

Including that in a new special page, and including that special page, that will need another post.

Posted in mediawiki, mysql | Tagged , , , , , | Leave a comment

a typography learning book for kids and grown-ups who don’t feel like that, and 29 typography tutorials

Posted on by fulgen | Leave a comment

some 21 mysql best practices to follow

Posted on by fulgen | Leave a comment

php coding standards

Why coding standards? In big projects, in any project, they’re essential: understandeable, much easier, solid code. Perfect, mandatory for a team. The objective is to have all decisions documented, choices and standards that I will stick on when developing. Important thing is not to follow these guidelines, but to follow a set of them, whichever. It can be PEAR as this guy. My coding standards are based on Zend Framework Coding Standard for PHP, but some are mine. The result follows.

scope (as a table of contents)

As of today, topics in this php coding standards include:


php architecture

I work with the MVC pattern:

MVC - Model View Controller

Following this architecture, I prefer the Codeigniter framework. Codeigniter, in its wonderful yet easy and concise help, defines MVC as:

MVC is a software approach that separates application logic from presentation. In practice, it permits your web pages to contain minimal scripting since the presentation is separate from the PHP scripting.

  • The Model represents your data structures. Typically your model classes will contain functions that help you retrieve, insert, and update information in your database.
  • The View is the information that is being presented to a user. A View will normally be a web page, but in CodeIgniter, a view can also be a page fragment like a header or footer. It can also be an RSS page, or any other type of “page”.
  • The Controller serves as an intermediary between the Model, the View, and any other resources needed to process the HTTP request and generate a web page.

why a framework?

Frameworks provide us programmers with tested, ready-to-use tools to develop flexible and almost error-free applications effectively. PHP frameworks can include authentication classes, database access, caching, even web templates in case you need them. They help in the sense you can focus on design and business, and not in implementation details. You don’t have to reinvent the wheel for very common development needs.

why codeigniter?

Why not? It is lighter, easier, more flexible than symphony, cakephp and zend, support databases as Oracle which Kohana and Yii lack.

file structure

the-domain.com/
      app/
            config/
            controller/
            view/
            model/
            library/
            helper/
            (...)
      public/
            css/
            js/
            img/
            (...)

File name: low case a-z, underscore separation: emission_dataset.php. All files have .php extension (no .inc for security issues). For classes, the file has same name as the class contained in it, still low case.

For backoffice files, begin with underscore: _users.php.

version

It is controlled by subversion.

developing

While developing, I use these conventions in comments:

  • :TBD: to be done.
  • :BUG: and the number assigned by the bug tracker.
  • :WRN: some warning, maybe the code could be unstable depending on some conditions.


file formatting

file

Files are ASCII text with Western, ISO-8859-1 character encoding.

lines

  • Maximum line length: 80 to 120 chars.
  • Line terminations follow the windows standard: CRLF (both chr 13 and 10).

php tags

  • <?php: full open tag, available in all php configuration and thus preferred over the short one (), which can cause problems.
  • <?php= $val; ?> as inline tag (and even better, <?php echo $val; ?>).
  • Not using ?> at the end of a file to avoid possible injections.

indentation

  • Always 2 spaces and not using tabs, to avoid problems in different text editors and users.
  • Align when possible:
          $aColors = array( array( #FFF, #FFF, #FFF ),
                            array( #0FF, #F0F, #FF0 ),
                            array( #00F, #F00, #0F0 ),
                            array( #000, #000, #000 ) );
    

    or another example:

          $sName          = "";
          $iMaxFileSizeKb = 128;
          $aTypeAllowed   = array( "jpg", "gif", "png" );
    


naming convention

classes

Capital first letter, underscore between words. Class name must match controller's and file name (except first letter). That means that each class must go in a different file. Models add "_model" at the end, as Dataset_model. Use of acronyms is allowed but without caps: Document_pdf and Document_pdf_model. Even if a word is an acronym, it must not be written in all caps (HTML, for example, would become Html).

functions and methods

Begin with small caps, then words begin with caps. No underscore between words. If suitable, use "Get" or "Set" as beginning. Explain what they do: getErrorCode, calcEmissions, showPdf, loadDataset.

variables

Since PHP vars can be of any type, even change in the same script, I prefer using the hungarian notation for stating the type with the first lower letter, then same as functions. Always initialized before used: $aColors = array();, $bEndFile = false;. Exceptions:

  • Short loops: $i, $j.
  • Coordinates: $x, $y, $z.
  • Database: $sql, $query, $db, $rs.

I do not use global vars. When needed, either a regular var in config or a session one.

constants

All caps and underscore between words: MAX_FILES_ALLOWED.


coding style

parenthesis

I do know that language constructs as if are different than functions as str_replace. But both work the same way and return values, so I try to keep same style with these calls. Always put spaces when using parenthesis, it is much easier to read:

 if( $sUserType === "admin" )
 $iLastUser = count( $aUsers ) - 1;
 $sLastUser = $aUsers[ $iLastUser ];
 $oDataset->loadPdf( $fName, $iFileSize, $sUrl );

braces

I always use braces in their own line:

  for( $i = 0; $i <= $iLastUser; $i ++ )
  {
    if( ! empty( $aUsers[ $i ] ) )
    {
      echo( "user: ", $aUsers[ $i ], "<br/>" );
    }
  }

strings

I prefer double quotes, but never rely on magic quotes. Single quotes are used inside.

$sql = "SELECT id FROM users WHERE name = 'Pau' ";

When using concatenation, the . operator is placed under the assignment. Concatenation and caps are used in queries as follow:

        $sql = "SELECT field1, field2 "
             . "  FROM table "
             . " WHERE field3 = 'somevalue' "
             . " ORDER BY field1 " ;

switch

Use continue and break sparingly, as they are masked go to. Always use a default. The switch follows this model:

switch( $erCode )
{
  case 1:
    ...
    break;
  case 2:
    ...
    break;
  default:
}

other

  • Never use global vars. Use session vars instead.
  • Use of echo( 1, " .- ", $var ); instead of echo 1 . " .- " . $var; or print.
  • Use of if instead of the ternary operator ? :.
  • The return clause never uses parents. And it helps debugging if there is a simple variable to return. Any calculations or function calls must be done earlier:
          function getTableValue( $sTable, $sField )
          {
              $sql = 'SELECT ' . $sField
                   . '  FROM ' . $sTable;
              $db->query( $sql );
              $val = $db->row[ $sField ];
              return $val;
          }
    
  • No use of magical numbers like if( $i > 15 ). Use variables and document them.
  • One statement per line. If possible, avoid embedded assignments like if( $file = fopen( $url ) )
  • Space after commas, as when writing.
  • Do not use abort or die, or the evil @ operator. Use a error handler, like:
          function exception_handler( $exception )
          {
            echo 'Uncaught exception: ',
                 $exception->getMessage(), '\n';
          }
    
          set_exception_handler( 'exception_handler' );
    
          throw new Exception( 'Uncaught Exception' );
    
  • Use of operators like ===, !== (value & type) instead of ==, != (just value, type is casted).
  • Do not rely on the default values like zero, null or false; always check if( $bGeneratePdf === true ).
  • Do not call functions in checking the end of a loop; assign them before:
          $iNumUsers = count( $aUsers );
          for( $i = 0; $i < $iLastUser; $i++ )
    


example

bad code

function copy($url,$dirname){
@$file = fopen ($url, "rb");
if (!$file) {
echo '<font color=red>Failed to copy
$url!</font><br<';
return false;
}else {
$filename = basename($url);
$fc = fopen($dirname."$filename", "wb");
while (!feof ($file)) {
$line = fread ($file, 1028);
fwrite($fc,$line);
}
fclose($fc);
echo "<font color=blue>File $url saved to
PC!</font><br>";
return true;
}
}

my code

function copyFile( $sUrl, $sDirName )
{
  $iBufferRead = 1024;
  try
  {
    $fIni = fopen( $sUrl, "rb");
  }
  catch(Exception $e) //this does not handle fatal errors, though
  {
    print("Couldn't open file");
  }
  if( !$fIni )
  {
    echo '<p class="error">Failed to copy',
         $sUrl, '</p>';
    return false;
  }
  else
  {
    $sFileName = basename( $sUrl );
    $fEnd = fopen( $sDirName . $sFileName, "wb" );
    while( ! feof( $fIni ) )
    {
      $sLine = fread( $fIni, $iBufferRead );
      fwrite( $fEnd, $sLine );
    }
    fclose( $fEnd );
    fclose( $fIni );
    echo '<p class="succeed">File',
         $sUrl, 'saved to PC!</p>";
    return true;
  }
}


documentation

Documentation must be compatible with phpDocumentor.

file

Each file starts with...

<?php
/**
 * some_file.php
 *
 * Explains what it is inside the file.
 *
 * @copyright 2009 geometrus all rights reserved
 * @license http://geometrus.com/license
 * @version $Id$  (cvs keyword)
 * @link (where the file is placed)
 * @author Fulgencio Sanmartin <f@geometrus.com>
 * @since File available since Release 1.5.0
 *
 * Audit:
 * 23/01/2009 [fulgen] created
 * 25/01/2009 [other]  added some functionality
 * 26/02/2009 [fulgen] solved bug #3341
 */

class

Apart from previous tags (see file), each class adds and is preceded of...

 * @package sample
 * @subpackage classes

function, method

Apart from previous tags (see file), each function or method adds and is preceded of...

 * @param string $param1 name to declare
 * @param string $param2 value of the name
 * @return integer
Posted in codeigniter, featured, php | Tagged , , , , , , | 2 Comments

a periodic table of visualization methods: http://www.visual-literacy.org/periodic_table/periodic_table.html

Posted on by fulgen | Leave a comment