Posts Tagged ‘PHP’

amMap for MediaWiki

Thursday, August 4th, 2011

For my worldwide Internet access project surfnext.com I developed an extension for MediaWiki to use amMap.

What is amMap?

amMap is a pretty cool Flash-based map which allows you to display geographical information. Check out the examples on amMap.com. It has been used on many pages world-wide, and now – thanks to SurfNext's needs – it is coming to MediaWiki!

What is MediaWiki?

It is the Wiki software which is behind Wikipedia and many other major wikis. SurfNext.com is also based on MediaWiki. Ah, the power of free software!

Why Flash, why amMap?

Because there is no free JavaScript-based map out there, which is not based on tiles. (Please post a link if you know any vector-based JavaScript map !!!)

Unfortunately iDevices (iPhone, etc) do not have Flash capabilities. Thus, you can't see the amMap on them.

Android has Flash support.

Download & Credits

Download version 0.5. (amMap v. 2.5.7 is included).

amMap requires you to leave the link to amMap (inside the map) intact, or to buy a commercial license.

I ask you to provide a back-link to my project SurfNext.com, if this extension is of value to you.

This extension is still in early beta, use at your own risk. Post comments about the extension on this blog page, thank you!

Installation

snAmmap requires MediaWiki 1.17 or higher, as it uses ResourceLoader. (Feel free to fork a version for earlier MediaWikis).

An alternative, of course, is to upgrade your Wiki. It is advisable, as the new release sports significant speed enhancements.

  • Put the snAmmap folder in your extensions folder.
  • Add require_once("$IP/extensions/snAmmap/snAmmap.php"); to your LocalSettings.php
  • If you want to, you can create custom data and settings files and put them somewhere in your Wiki installation path. (i.e. a folder custom)

Usage

Currently snAmmap only supports one map per page. After you have installed the extension, use the following tag in your Wiki where you want to include the map:

<ammap height="500px" width="500px" bgcolor="#FFFFFF" data_file="/custom/data.xml" settings_file="/custom/settings.xml">Placeholder text</ammap>

None of the tag's attributes are required, there are sensible defaults for them (falling back on the data_file and settings_file provided with amMap, for instance.)

  • height => sets the height of the map. Can be a percentage
  • width => sets the width. Can also be a percentage.
  • bgcolor => sets the initial background color, which can be modified in the settings file later.
  • data_file => sets the path (URL!) for the data_file. Can be a full URL with hostname, but you have to enable cross-site scripting, which is dangerous. Use a file from your server, preferably.
  • settings_file => sets the path for the settings_file

See the documentation of amMap for more details and information what you can modify.

Live Example

SurfNext.com uses the snAmmap extension on the main page in conjunction with custom data and settings files for a map which links to Wiki pages. It also has a dropdown menu from which you can select the individual countries by name, which also links to the Wiki pages.

SurfNext shows you how to obtain Internet access everywhere in the world. Feel free to join and participate!

Feel free to comment about SurfNext on this blog page.

Apache 2 not starting

Tuesday, March 22nd, 2011

After doing a apt-get upgrade your Apache does not start / does not serve connections? Read on!

somesystem.root# /etc/init.d/apache2 start
Starting web server: apache2[Tue Mar 22 18:18:02 2011]
(98)Address already in use: make_sock: could not bind to address 0.0.0.0:80
no listening sockets available, shutting down
Unable to open logs
failed!

Binding to adress 0.0.0.0:80 means accepting all connections. There is nothing wrong here, nor probably in the Apache setup files – which have been correct before.

The error can be caused by Apache 2 already running! Try ps awx to see all processes, look for Apache 2 and perhaps rotatelogs.

After killing the processes using kill -9 pid_one pid_two (replace pid_one pid_two with the appropriate process ids – you can specify multiple at once) try starting apache again (using apache2ctl -k start for instance).

This time Apache should start without problems. But it will not serve requests, and the Apache PID may not be written. (Thus, apache2ctl will assume that Apache is not yet running!)

Check your error log for the last entries. In my case the following entry was the key to fixing the problem:

PHP Warning: [eAccelerator] This build of "eAccelerator" was compiled for PHP version 5.2.6-1+lenny3. Rebuild it for your PHP version (5.2.6-1+lenny10) or download precompiled binaries.

in Unknown on line 0
PHP Fatal error: Unable to start eAccelerator module in Unknown on line 0

PHP's error was blocking the whole Apache! The quick solution for this particular problem (yours may be different) was to edit /etc/php5/apache2/php.ini and comment the lines setting up eAccelerator. (You need to use ";" as comment character for this file).

After the fix, killing the running Apache process(es), and starting Apache again, it resumed normal operation.

jQuery AJAX & Internet Explorer

Wednesday, May 26th, 2010

Internet Explorer getJSON trouble

This piece of code initially did not work for me on IE:

$.getJSON("../inc/exercise_ajax.php?" + $(this).serialize(), function(json)

FireFox worked without problems.

The reason is that my JSON code was not well-formed. It had a comma (',') too much.

Here's the code which I use in PHP to create my JSON (braces omitted):

foreach($answers as $question => $answer){
$outstr .= '"q'.$question.'": ';
if (isset($_GET[$question])){
if ($_GET[$question] == $answer) $outstr .= 'true';
else $outstr .= 'false';
} else $outstr .= 'null';
$outstr .= ',';
}
echo chop($outstr,',');

You have to chop off the trailing comma – if you don't, IE will choke on it and your callback function won't be executed.

Internet Explorer & AJAX caching

Yes, Internet Explorer caches your requests. You've got to empty the browser cache before testing the fix I mentioned. Also, you should append a unique parameter to suppress caching, i.e. the current timestamp. Example:

var now = new Date();
// submit with AJAX
$.getJSON("../inc/exercise_ajax.php?ts=" + now.getTime() + '&' + $(this).serialize(), function(json)

Adding content to the head of Lectora HTML output

Sunday, May 23rd, 2010

There's the possibility to add an "external HTML object". If you choose "header scripting", your content would be added to the <script> section of Lectora in the header. In most cases that's not what you want to achieve. There's another strange option "Top of file scripting" which simply inserts your content just before the <!DOCTYPE> tag. The only use I can see for this is for PHP scripting which needs to be done before any output was sent to the browser (i.e. header modification).

What you want to choose to include arbitrary content to the <HEAD> section of Lectora generated HTML documents is the "META Tag" option. Unfortunately, this does not allow to include external .txt files, so you have to paste your code in Lectora's input window. (You would have needed to update the .txt file anyways, as Lectora stays with the initial .txt file version instead of updating it from the hard disk every time. That way it's not really a big loss that you can't use .txt files.)

And there IS a way to include a file's contents in the header. Just drop a PHP file somewhere on your server and include it using the following as a "meta tag":

<?php include('your/path/to/header.php');?>

Adding aliases to Concrete5 pages programmatically.

Sunday, April 4th, 2010

Suppose, you want to provide legacy URLs when porting the page to a new version. I need to do this, as I am writing the IdeaDay Import Wizard.

An example:

  • The new page will be under /my/new/page
  • You want a legacy alias under /legacy_path/legacy_name

There is a function $page->addCollectionAlias($c); which will alias your Collection UNDER another Collection (essentially adding the page with the same name elsewhere). We could use this, but would need to work around the new page's name and cHandle (which will change: page != legacy_name)

How does C5 handle this internally, when editing page aliases?

/concrete/startup/process.php contains the code (look for else if ($_POST['update_metadata']) and continue to read).

It essentially sets $data['ppURL'] to the aliases (new AND old), and uses $page->update($data);

There is one important thing to consider: to add a new path, the key needs to be a string! This had me baffled for one hour.

So, the entire code to add one new alias, AND keep all the old ones will be:

$this_page_paths = $in_pg->getPagePaths();
$new_paths = array();
foreach($this_page_paths as $path){
if (!$path['ppIsCanonical']) {
$new_paths[$path['ppID']] = $path['cPath'];
}
}
$new_paths['add_path'] = $add_alias;
$data = array();
$data['ppURL'] = $new_paths;
$in_pg->update($data);

$in_pg is the page you want to add the alias to. It is important that you check for the path being canonical, else your main page path will be overwritten (and the page will be redirecting to /). The new path ($add_alias) is added with a string (it does not matter which string you use).

We could use rescanPagePaths to do it directly, but we should not: update fires on_page_update events, for instance.

Now to the second part: modifying .htaccess to provide compatibility.

RewriteRule ^(.*)\.phtml(.*)$ $1$2 [L]

By adding this rule you will be stripping out .phtml from your links -> thus, compatibility with the following path from our example would be preserved:

/legacy_path/legacy_name.phtml

This rewriting is necessary, as Concrete does not allow dots (.) in page paths – it replaces them by an underscore.

Concrete5 errors

Wednesday, March 31st, 2010

Fatal error: Class 'CollectionAttributeKey' not found in (…)/concrete/models/collection.php on line 183

This class is defined in concrete5.3.3.1\concrete\models\attribute\categories\collection.php

The problem is easily resolved by loading the appropriate model in your code:

Loader::model('attribute/categories/collection');

Concrete5 :: interacting with the database

Wednesday, March 24th, 2010

The C5 API has a class Database in the core package (libraries/database.php). Alas, this is not the documentation we're looking for (we're looking for query, etc. methods, which are not present there).

Actually the methods used come directly from the included ADODB librarary. You can download a documentation here.

Usage:

//Load the Database Layer.
$db = Loader::db();
//quote the string we'll be inserting (use get_magic_quotes_gpc() as second parameter to avoid double escaping!)
$source = $db->qstr($source, get_magic_quotes_gpc());
$content = $db->qstr($content);
$sql = "insert into IdImportWizardSources (source, content) ";
$sql .= "values ($source,$content)";
if ($db->Execute($sql)===false) {
//error handling
echo 'error inserting: ' .$db->ErrorMsg();
}

FormHelper select

Friday, March 19th, 2010

Not understanding the Concrete 5 API comment on the select function of the Form Helper, I looked into the source:

/**
* Renders a select field. First argument is the name of the field. Second is an associative array of key => display. Second argument is either the value of the field to be selected (and if it's blank we check post) or a misc. array of fields
* @param string $key
* @return $html
*/
public function select($key, $values, $valueOrArray = false, $miscFields = array())

Select builds a SELECT Dopdown with OPTIONS. That much I already understood from the API.

Here's my explanation of the parameters passed in to select:

  • $key: the name of the element to be created.
  • $values: an array of options, stored as $k=>$value. Used like this:
    '<option value="' . $k . '" ' . $selected . '>' . $value . '</option>';
  • $valueOrArray: this can either be set to the default value to be selected (use the option value, not the displayed text between the tags) OR it can be an array and is used as the array to populate $miscFields (see explanation there), omitting the default value. A bit unusual perhaps, probably it's a timesaver when you code these forms a lot.
  • $miscFields: An associative array ($k => $value): insert additional keys into the tag (i.e. multiple="multiple"

The fun in using select is, it STORES your settings between sessions. Boy, I should have used it earlier, when hand-coding this for other parts of the project.

Another note on ValidationErrorHelper:

/**
* Returns whether or not this error helper has more than one error registered within it.
* @return bool
*/
public function has() {
return (count($this->error) > 0);
}

As one can read from the source above, the Validation Helper returns whether there are errors (even if it is only one) or there are none!

Server Management Software

Monday, March 8th, 2010

Wir sind dazu bereit, den nächsten Schritt zu gehen und die Verwaltung des Webservers von manuell auf semi-manuell umzustellen.

Unser Mailsystem wird nach wie vor vom Websystem abgekoppelt laufen – auf Zimbra-Basis.

Für den Webserver selber rüsten wir eine Server Management Software nach. Sie muß einen typischen LAMP Server unterstützen (Linux – Debian / Apache / MySQL / PHP)

Hier sind die Kandidaten:

  1. SysCP

    Gut dokumentiert, aktive Community, interessanter Funktionsumfang (inklusive Resellern die ihre Kunden selbst administrieren können usw.), deutsches User Interface verfügbar.

    Natürlich Open Source.

  2. Kloxo / HyperVM

    Interessant für unser Setup (OpenVZ, mehrere VPMs, …); allerdings evtl. nur auf englisch und massiver Overkill. Es heißt, dass es als Open Source released wurde, jedoch ist auf der Firmenseite etwas von Lizenzkosten die Rede …

  3. http://www.virtualmin.com/

    Virtualmin ist eine weitere Möglichkeit. Hier sticht ebenfalls keine Sprachunterstützung heraus, das System ist komplex und deckt z.B. detaillierte CPU Leistung usw. Statistiken ab.

    Unterstützt einen hohen Grad von Sicherheit bei PHP – die Prozesse werden unter dem jeweiligen User ausgeführt, mit suexec und mod_fastcgi. Siehe auch: http://en.wikipedia.org/wiki/Webmin

  4. OpenLSM

    Eine indische Software mit einer schönen, aber leider nicht so informativen Webseite. In der Feauture Liste schaut das Produkt gut aus – Anlegen von Resellern, Monitoring, … Unterstützt auch Subversion.

  5. VHCS

    Obwohl auf anderen Seiten behauptet wird, dass das Projekt tot sei, ist es nicht so. Die Jungs arbeiten gerade an Release 2.6, der Web 2.0 in VHCS bringen soll. Das Interface schaut übersichtlich und aufgeräumt aus.

  6. OpenPanel

    Schaut sehr, sehr gut aus – ein JavaScript zentriertes UserInterface. Leider ist es seit Juli 2008 in Beta 0.9.5 stehen geblieben. Eine 1.0 steht fast vor der Tür – sie wird Debian 5.0 unterstützen. Definitiv einen Blick wert – auch wenn es erstmal nur in Englisch ist.
    Wird von  PanelSix entwickelt, hier ist die Doku.

Hier ist noch ein Überblick auf Wikipedia (EN).

MySQL

Thursday, February 25th, 2010

[25-Feb-2010 16:15:46] PHP Warning: mysql_real_escape_string() [<a href='function.mysql-real-escape-string'>function.mysql-real-escape-string</a>]: Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2) in … on line 38
[25-Feb-2010 16:15:46] PHP Warning: mysql_real_escape_string() [<a href='function.mysql-real-escape-string'>function.mysql-real-escape-string</a>]: A link to the server could not be established in … on line 38
(…)

Lösung des Problems:
die Funktion mysql-real-escape-string erfordert eigentlich zwei Parameter: zuerst den $unescaped_string, dann die resource $link_identifier. Lässt man zweiteres weg, versucht MySQL die aktuell zuletzt geöffnete Verbindung zu benutzen.

Ich habe in meinem Skript den Zugang zur Datenbank erst danach geöffnet. (Das ist der wichtigste Unterschied zwischen mysql_escape_string und mysql_real_escape_string – ersteres erfordert KEINEN Zugriff auf die Datenbank!)