Michal Čihař - Archive for 1/2008

Můj první modul pro Drupal

Jakmile jsem se rozhodl používat Drupal pro české stránky o phpMyAdminovi , bylo mi jasné, že si časem nevystačím s tím co už pro něj někdo napsal, ale budu muset vytvořit něco sám. Naštěstí dokumentace k Drupalu je celkem dobrá (rozhodně patří k tomu lepšímu co se mezi open source vyskytuje), tak vytvoření jednoduchého modulu nebylo až tak složité.

Chtěl jsem na phpMyAdmin.cz začít používat některé ze služeb měřící návštěvnost. Místo upravování šablon mi jako lepší řešení přišlo napsat si modul, který udělá co potřebuju a nebudu muset zasahovat do originálních šablon (a tím se vyhnu problémům při aktualizaci). Vzal jsem existující modul pro Google analytics, protože mi připadal podobný, ale nakonec toho z něj moc nezůstalo :-). Asi po hodině už jsem měl verzi, která fungovala celkem dobře a tak jsem si říkal, že by nebylo od věci to někde zveřejnit.

Jako logické místo se jeví Drupal.org a i tento postup je tam vzorně zdokumentován. Žádost o CVS přístup byla vyřízena během pár dnů, a já už mohl commitovat svůj první kód do jejich repository. K mému překvapení commity někdo sleduje, protože asi hodinu po prvním commitu už mi přišla reakce od někoho, že přesně takový modul potřeboval :-). Tak jsem jenom dokončil vyčištění a další den vyšla první verze modulu Český audit .

Gammu stable version 1.18.0

Good news everyone, first stable Gammu release in this year is out. Since 1.17.92 only few small fixes in SMS decoding and AT engine did happen, but there is quite big list of changes compared to 1.17.0:

  • Fixed decoding of an empty SMS.
  • Fixed some mistakes in API documentation.
  • Fixed compilation under MS Visual C++ Express.
  • Various small fixes if AT driver.
  • Add simple shell script to generate JAD file from JAR.
  • Added support for adding memory entries to 6510.
  • Phone features now can be defined in configuration, so there is no need to modify common/gsmphones.c for testing different settings.
  • Config file loading behaves more consistent in lookup. In some cases it can now find different configuration file.
  • Fixed crash when there are too many messages (bug #466).
  • Fixed crash when printing messages on Windows (bug #476).
  • Do not ask phone for IMEI so often (bug #480).
  • No need to set LD_LIBRARY_PATH for tests.
  • Properly wait for SMSD child processes (bug #486).

You can download from usual place: http://cihar.com/gammu/.

My first Drupal module

As I use Drupal for Czech phpMyAdmin pages, it was only a matter of time till I will have (or want) to add some functionality. My first Drupal module is quite trivial, but anyway I already got positive feedback on it just after committing to Drupal CVS :-). Today I finished little cleanup which my initial version required and I decided to make a first release out of it.

And what I'm still talking about? It's a module for adding measuring code for various web auditing systems used in Czechia. I didn't wanted to hack this somehow into templates and module which will provide block with those looks as best solution to me. You can get it on Drupal pages.

Oblíbené dotazy

Pokud často používáte nějaký komplikovanější dotaz, tak vás asi nebaví ho pokaždé zadávat znovu. Proto byla do phpMyAdmina přidána funkce pro ukládání a používání oblíbených dotazů. Pro její použití ovšem potřebujete mít zapnutou podporu pro rozšířené funkce .

Vytváření oblíbeného dotazu

Dotaz můžete vytvořit jakýmkoliv způsobem, třeba ho zadat jako SQL, nebo pomocí vyhledávací stránky. Po jeho provedení uvidíte pod výsledky rámeček pro přidání SQL dotazu do oblíbených, kde stačí zadat jméno a phpMyAdmin so ho bude pamatovat. Pokud dotaz nechcete spouštět, můžete oblíbený dotaz rovnou vytvořit na SQL stránce . Tato možnost je obzvláště vhodná pro dotazy, které nevrací žádný výsledek (například úprava tabulek nebo vkládání nových záznamů).

Oblíbený dotaz není omezen na jediný SQL příkaz, ale jsou zobrazeny jen výsledky toho posledního, takže není moc užitečné do něj vkládat víc dotazů vybírající nějaké řádky.

Při vytváření můžeme dotaz pojmenovat libovolně. Pokud ho ovšem pojmenujeme stejně jako se jmenuje některá tabulka v databázi, phpMyAdmin tento dotaz použije při procházení této tabulky. Tímto můžeme například omezit počet zobrazených sloupců při prohlížení tabulky.

Práce s oblíbenými dotazy

Již vytvořený dotaz se objeví na SQL stránce , odkud ho jeho vybráním můžeme spustit.

Oblíbený dotaz upravíme podobným postupem jako ho spouštíme. Jen je zapotřebí na SQL stránce zvolit „Zobrazit“ místo výchozího „Provést“. Tím bude dotaz zobrazen v editačním poli pro SQL a máme možnost ho po úpravách znovu uložit. Pokud chceme přepsat starý dotaz, nesmíme zapomenout zaškrtnout „Přepsat existující oblíbený dotaz stejného jména“.

Pokud již oblíbený dotaz nepotřebujeme, můžeme ho opět na SQL stránce vymazat zvolením možnosti „Odstranit“.

Přístup k dotazům

Standardně má k dotazu přístup pouze uživatel, který ho vytvořil, protože většinou nechceme aby k našim datům měli přístup ostatní. Pokud však chceme dotaz sdílet, nabízí nám phpMyAdmin tuto možnost, stačí při vytváření (nebo úpravách) zaškrtnout „Umožnit všem uživatelům používat tuto položku“ a pak všichni uživatelé budou moci používat tento dotaz. Toto také znamená, že ostatní uživatelé budou moci dotaz upravit a smazat.

Parametry oblíbených dotazů

Zatím jsme oblíbené dotazy vytvářeli jen pevně dané. phpMyAdmin ale umožňuje do dotazu začlenit i volitelnou část, která se přidá při zadání parametru. Hodnota parametru bude vložena namísto [VARIABLE] a zakomentovaná část dotazu bude odkomentována. Takový dotaz pak může vypadat třeba takto (používá se databáze sakila ):

 
  SELECT * FROM `city`
/* WHERE `city`.`country_id` = [VARIABLE] */
 

Pokud tedy parametr nezadáme, vybere dotaz všechny města, pokud ho zadáme, vybere jen města v dané zemi.

Gammu test version 1.17.92

New Gammu testing version is out. This is mostly bug fixing release, but you should be able to do addnew with 6510 driver now. Full list of changes:

  • Fixed some mistakes in API documentation.
  • Fixed compilation under MS Visual C++ Express.
  • Various small fixes if AT driver.
  • Add simple shell script to generate JAD file from JAR.
  • Added support for adding memory entries to 6510.

You can download from usual place: http://cihar.com/gammu/.

When to release 1.0?

This is not about any particular project, but more a generic thought. When should be something considered to be stable enough to be released as 1.0? Over ages I started several projects which are in different quality right now and this is maybe not completely related to version they use.

Let's take one of older ones - Wammu. It was started long time ago, it really does not get any major code changes for several years and I still don't want to make 1.0 release there. The reason is that I think that many things could be done better there. However there are quite lot of users which use it and they probably consider it stable enough :-). But they will have to live with 0.x versions as I do not plan 1.0 at all for now even if it maybe deserves it :-).

Different case is Ukolovnik. It does not have tons of features, but it's enough for me and it will be 1.0 soon. I have features to add, but I don't thing that RPC interface has to be in 1.0, it can be just thing added later.

Že se ještě vůbec snažím někomu radit

Chápu, že občas na jabber konferenci pro phpMyAdmina vleze někdo kdo má problémy s MySQL. Ale když už někdo neví co dělá a chce provozovat redakční systém v PHP, tak by aspoň mohl mít trochu slušnosti. Pojmenovat se aaa na důvěryhodnosti moc nepřidá (a koneckonců anonymitu taky ne, stejně IP adresu vím ;-)) a po prvním dotazu "hele kde mám zjistit udaje MySQL?" už se člověk nemůže ubránit pocitu co že to za blbce sem zase dorazilo. Nicméně to mě neodradilo od toho se mu pokusit poradit, ale dobře míněná snaha stejně přišla vniveč. Ostatně posuďte sami . No nic je na čase jít spát.

Vlastní exportní formát

Před týdnem jsme se dozvěděli, jak exportovat data do podporovaných formátů. Co ale dělat, když potřebujeme data ve vlastním formátu? Napsat si vlastní exportní modul není nic těžkého, jak na to se dozvíte v dnešním článku.

Začátek

Nejdříve si rozmyslete, co všechno od exportu budete potřebovat a jaké možnosti nastavení bude export mít. Vždy je lepší si nejprve ujasnit požadavky, než se vrhneme na programování. Pro ukázku v tomto článku budeme vytvářet export do textového souboru, který půjde dále zpracovat pomocí Texy! . Nastavení použijeme stejná jako mají ostatní podobné exporty, tedy možnost vypnutí dat nebo struktury, zobrazení jmen sloupců a text, kterým nahradíme NULL hodnoty.

Hlavička

Každý plugin obsahuje hlavičku, která se provádí při načítání pluginů. Ta definuje jednak informace o pluginu a také parametry, které bude možné nastavit na stránce s exporty. Pro náš export tedy bude základní hlavička vypadat takto:

 
  <?php

/*Texy! export for phpMyAdmin */

if (isset($plugin_list)) {
    /* Jméno zaregistrovaného pluginu musí být stejné jako jméno souboru */
    $plugin_list['texytext'] = array(
        'text' => 'Texy! text',         /* Jméno pluginu které se zobrazí uživateli */
        'extension' => 'txt',           /* Přípona vygenerovaného souboru */
        'mime_type' => 'text/plain',    /* MIME typ vygenerovaného souboru */
        /* Definice parametrů: */
        'options' => array(
            array('type' => 'bool',
                'name' => 'structure',
                'text' => 'strStructure',
                'force' => 'data'),
            array('type' => 'bgroup',
                'name' => 'data',
                'text' => 'strData',
                'force' => 'structure'),
            array('type' => 'text',
                'name' => 'null',
                'text' => 'strReplaceNULLBy'),
            array('type' => 'bool',
                'name' => 'columns',
                'text' => 'strPutColNames'),
            array('type' => 'egroup'),
            ),
        'options_text' => 'strOptions',
        );
} else {

/* Sem přijde kód pro export */

}
?>
 

Pokud nyní soubor s tímto PHP kódem uložíme jako libraries/export/texytext.php , měl by phpMyAdmin už tento plugin zobrazit na stránce pro export.

Implementace exportu

Pro vlastní export je potřeba implementovat několik funkcí, které mají za úkol získat data z MySQL a poslat je na výstup pomocí funkce PMA_exportOutputHandler . Tato funkce zajišťuje zpravování výstupního bufferu, kompresi a posílání dat uživateli nebo ukládání na server. Vrací false, pokud operace selhala.

Funkce, které musíme implementovat jsou tyto:

  • PMA_exportComment
  • PMA_exportFooter
  • PMA_exportHeader
  • PMA_exportDBHeader
  • PMA_exportDBFooter
  • PMA_exportDBCreate
  • PMA_exportData
  • PMA_exportStructure

Všechny by opět měly vrátit false, pokud se něco nepodařilo. Funkcí je sice hodně, ale to je jen z důvodu usnadnění psaní exportů do rozličných formátů. Jejich názvy jsou snad celkem výstižné, takže ani nebudu popisovat k čemu která slouží. Pro náš případ potřebujeme jen funkce PMA_exportDBHeader , PMA_exportData a PMA_exportStructure , ostatní mohou jen vracet true a nic nedělat.

PMA_exportDBHeader

Tato funkce má za úkol vypsat hlavičku exportu a bude tedy poměrně triviální:

 
  function PMA_exportDBHeader($db) {
    return PMA_exportOutputHandler('===' .
        $GLOBALS['strDatabase'] . ' ' . $db . "\n\n");
}
 

PMA_exportData

Teď se již dostáváme ke komplikovanějšímu úkolu – exportu dat. Začneme opět nadpisem, aby uživatel věděl, o jakou tabulku se jedná:

 
  if (!PMA_exportOutputHandler('== ' . $GLOBALS['strDumpingData'] . ' ' . $table . "\n\n")) {
    return FALSE;
}
 

Jako další krok potřebujeme načíst data z MySQL. Pro to použijeme DBI vrstvu phpMyAdmina:

 
  $result      = PMA_DBI_query($sql_query, null, PMA_DBI_QUERY_UNBUFFERED);
$fields_cnt  = PMA_DBI_num_fields($result);
 

Uživatel měl možnost si vybrat, zda chce zobrazit v hlavičce jména sloupců. Zde poprvé použijeme přístup k parametrům a podle jeho hodnoty případně zobrazíme hlavičku:

 
  global $what;

if (isset($GLOBALS[$what . '_columns'])) {
    $text_output = "|------\n";
    for ($i = 0; $i < $fields_cnt; $i++) {
        $text_output .= '|' . htmlspecialchars(stripslashes(PMA_DBI_field_name($result, $i)));
    } // end for
    $text_output .= "\n|------\n";
    if (!PMA_exportOutputHandler($text_output)) {
        return FALSE;
    }
} // end if
 

Nyní nám už jen chybí vypsat data z databáze uživateli:

 
  while ($row = PMA_DBI_fetch_row($result)) {
    $text_output = '';
    for ($j = 0; $j < $fields_cnt; $j++) {
        if (!isset($row[$j]) || is_null($row[$j])) {
            $value = $GLOBALS[$what . '_null'];
        } elseif ($row[$j] == '0' || $row[$j] != '') {
            $value = $row[$j];
        } else {
            $value = ' ';
        }
        $text_output .= '|' . htmlspecialchars($value);
    } // end for
    $text_output .= "\n";
    if (!PMA_exportOutputHandler($text_output)) {
        return FALSE;
    }
} // end while
 

A uvolnit výsledky dotazu a vrátit návratovou hodnotu:

 
  PMA_DBI_free_result($result);
return TRUE;
 

PMA_exportStructure

Export struktury je asi nejnáročnější a určitě nejrozsáhlejší, nicméně neobjevují se zde již žádné nové věci týkající se exportu, proto se na její celý kód podívejte sami v přiloženém souboru. V úvodu se načtou z MySQL parametry tabulky, poté pomocí funkcí phpMyAdmina načteme informace o relacích a MIME typech sloupců a tyto informace zformátujeme do Texy!.

Hotovo

A tím by mělo být vše hotovo. Plugin vyzkoušíme a pokud to uznáme za vhodné, pošleme do patch trackeru , aby mohl být náš plugin začleněn v další verzi phpMyAdmina.

Celý hotový exportní plugin naleznete v příloze článku.

Přílohy:

Toshiba ACPI keys, HAL and friends

Long time ago I used FnFX to handle events from ACPI keys on my Toshiba notebook. However when reinstalling notebook because of disk crash, I thought there must be a cleaner way to handle these and I found patch for acpid which added handling of these special events.

However I really didn't like patching acpid on every update and there didn't seem to be chance to merge it upstream, so I started to look for better solution. After another amount of googling, I found that HAL already has some support for Toshiba hotkeys. Unfortunately it is now disabled in Debian because most key did not emit anything using HAL.

Okay, let's fix the HAL, maybe it will get later enabled. Converting FnFX keymap to C code was quite easy and I made a patch for HAL to add support for all keys. Hopefully it get merged soon and I can then file bug on Debian package to reenable Toshiba support in HAL.

Meanwhile I'd like to find some generic way of configuring what happens on these events. For now I hacked simple Python script which listens to DBUS events and invokes appropriate commands for keys, but I hope that some such tool already exists and I just missed it. If you know something, please let me know at michal@cihar.com.