Elxis CMS Forum

Support => Elxis 2008 developers guide => Topic started by: datahell on April 28, 2007, 10:58:53

Title: Elxis developers guide
Post by: datahell on April 28, 2007, 10:58:53
** This is an online and under construction developers/compatibility guide for Elxis CMS **


ELXIS CMS
Developers guide

Make cross-platform compatible applications for Elxis CMS
Convert mambo/joomla components to Elxis compatible
Author: Ioannis Sannos (Elxis Team)
Last update: 2008-05-29


Index
0. Introduction
1. UTF-8
2. Files handling
3. Language (frontend)
4. Locale
      Elxis languages names and locales list (https://forum.elxis.org/index.php?topic=1375.0)
5. XML language
      Click here for information on custom XML language files (CX_) (https://forum.elxis.org/index.php?topic=717.0)
6. Installation
7. Uninstall
8. Language (backend)
9. Language (logic)
     UPL (Users Preferable language) (https://forum.elxis.org/index.php?topic=1688.0)

10. Database, ADOdb and queries
11. Access system
12. Creating installation packages


0. Introduction
Even if Components are applications of the same type their internal functions may vary a lot depending on the task that each one has to perform and the way they have been build. So, it is almost impossible to have an ultimate conversion guide from non-compatible to compatible components for Elxis CMS. Taking this under consideration in the current guide we will examine the Elxis specialties and the most basic differences between Elxis and Mambo/Joomla from the developer’s point of view to end in some general guidelines. At the end of each chapter there is a short summary with the basic guidelines.


1. UTF-8

1a. UTF-8 in general
In Elxis we use a single encoding for any language. This is UTF-8 (8-bit UCS/Unicode Transformation Format). UTF-8 is a variable length Unicode’s character encoding. It is capable to represent any character and it is a sequence of ASCII. In the ASCII model each character is consisted by 1 byte (1 byte = 8bit, each bit can have a value of 1 or 0). In UTF-8 a character can have 1 to 4 bytes length (8 to 32 bits) depending on the Unicode symbol we wish to represent. Only one byte is needed to encode the 128 US-ASCII characters. Two bytes are needed for Latin letters with diacritics and for characters from Greek, Cyrillic, Armenian, Hebrew, Arabic, Syriac and Thaana alphabets. Three bytes are needed for the rest of the Basic Multilingual Plane (which contains virtually all characters in common use). Four bytes are needed for characters in other planes of Unicode.

A logical consequence of the above is that a file will be larger in size if it contains characters above ASCII (non-English). For example a component’s Russian translation file will be bigger than the English one. Let’s do a small experiment to better understand this. Create a blank file utf-8 encoded and write in it 1000 times the first letter of the Latin alphabet (a). Save this file. This file will have size of 1000bytes (1 byte per character) or 1KB. Now let’s write in another utf-8 encoded file the first letter of the Greek alphabet (alpha - α). Save this file. This file will have size 2000bytes (2 bytes per character) or 2KB. You see that even if the number of characters in the 2 files is the same the second file’s size is double. This is because we need two bytes to represent the Greek letter alpha (α) in UTF-8.

1b. UTF-8 and PHP
PHP is in able to handle UTF-8 encoded strings. UTF-8 will be imported as the standard encoding in PHP 6. Till then, to bypass the PHP weaknesses, we implemented a special class to handle multi-byte strings. This is the eUTF class (abbreviation of Elxis UTF) which you can call statically everywhere inside Elxis. But why we did such a thing?

PHP has a series of functions for handling strings. These are strlen, substr, strtoupper, strtolower, str_replace, trim, strpos etc. These functions return wrong results when we feed them with multi-byte character strings as inputs. This is why neither Mambo nor Joomla support correctly UTF-8. UTF-8 is not only the language files encoding, it must be supported by the system. We will examine some examples bellow to better understand this.

substr(string, int start, int length)
Function substr() returns the portion of a string specified by the start and length parameters. Let’s say we want to take the first three characters of the word 'elxis'. We write:

Code: (php) [Select]
substr('elxis', 0, 3);This will return: 'elx'

Be careful: PHP does not return the characters but the bytes!

If the characters belong to the ASCII plane then each character is represented by 1 byte and everything works fine. But if any character in the string uses more than 1 byte (UTF-8) then we will have a huge problem. Let’s use as input in the same function the Greek name of elxis (έλξις). Function substr('έλξις', 0, 3) will return 3 bytes. The first two will be the Greek letter epsilon with ascent 'έ' (we need two bytes to represent έ) and the third byte will be a half(!) Greek letter lamda (λ – we also need two bytes to represent lamda)! This is usually appears in our browsers as a square or another strange symbol and this is because the web browser can not understand what this character is.

To bypass this problem in Elxis instead of using the standard PHP function substr we will use the utf8_substr function of the eUTF class.

Code: (php) [Select]
eUTF::utf8_substr('έλξις', 0, 3);The above will return as output the right value: 'έλξ'.


strlen(string)
Function strlen returns the length of a string. But, as in the substr case, strlen does not returns the number of characters, as it should do, but the number of bytes. So, strlen('έλξις') will return the value of 10 (each character is consisted by two bytes, 5X2=10 bytes in total)! An other example: strlen('aα') will return 3!

So, when we wish to find the length of a multi-byte string we must use the utf8_strlen function of the Elxis' eUTF class. In our example:

Code: (php) [Select]
eUTF::utf8_strlen('έλξις');The above will return the right value (5).

As you may understand if we don’t use the eUTF's functions then all the checks on multi-byte strings will return wrong results which can lead to serious problems even for the security of our site. Elxis Core and build-in components, modules etc as well as the add-ons created by Elxis Team or GO UP Inc and distributed by elxis.org website are utf-8 aware and can be safely used. We are not responsible for any other third party add-on that you may try to use in Elxis CMS without being UTF-8 aware.


1c. When we use the eUTF class
Besides the eUTF class always returns right outputs independently if we use ASCII or UTF-8 encoding inputs it is not recommended to be always used. This is because it needs more checks and CPU power to output the result so there is a small delay. Even if this delay is almost zero it exists. So, we don’t need to use eUTF functions in cases that we know that the input is not a UTF-8 encoded string as for example an Elxis file name. Namely you don’t need to write: eUTF::utf8_strlen('com_access.php') to find the length of the 'com_access.php' string. In this occasion we will use the standard PHP's function strlen. But we must always use the eUTF class in cases we have to do with multi-byte encoded strings.


1d. Where I can find more information?
Open Elxis file /includes/Core/utf8.class.php to see all the available function that class eUTF supports.


1e. Chapter's conclusion - Compatibility guide
Inorder to convert a Mambo/Joomla component to an Elxis compatible one we must replace all the standard PHP functions that handle multi-byte character strings with those from the eUTF class.
Title: Files handling
Post by: datahell on April 28, 2007, 18:42:38
2. Files handling

2a. FTP support
Elxis has build-in FTP (File Transfer Protocol) support. FTP solves many problems related to file handling such as wrong file permissions and allows you to handle non-writable by PHP files. As long as FTP has been enabled in the Elxis global configuration is called automatically and only when needed. When FTP access is needed by a script Elxis will automatically connect to your FTP account do your job and automatically get disconnected when finish.

2b. File Manager
For file handling we have implemented in Elxis the File Manager class which you can call everywhere in Elxis via the $fmanager object. File Manager is FTP enabled and also allows you to work with files much easier.

Example of usage 1
Let’s say we wish to open a file named 'myfile.txt' and read it's contents. Using the PHP's standard way we should write something like this:

Code: (php) [Select]
$handle = fopen('myfile.txt', 'r');
$contents = fread($handle, filesize('myfile.txt'));
fclose($handle);

Using the File Manager the same task is much easier and more understandable:

Code: (php) [Select]
$contents = $fmanager->readFile('myfile.txt');
Example of usage 2
Let's say we wish to get the files that contained in the 'images' directory and to save these in an array. Using the PHP's standard way we should write something like this:

Code: (php) [Select]
$xfiles = array();
if ($handle = opendir('images')) {
   while (false !== ($file = readdir($handle))) {
       if ($file != "." && $file != "..") {
           array_push($xfiles, $file);
       }
   }
   closedir($handle);
}

Using the File Manager we just need to write this:

Code: (php) [Select]
$xfiles = $fmanager->listFiles('images');
Example of usage 3
In this example we will examine the deletion of a file. We start with the PHP's standard way:

Code: (php) [Select]
unlink('myfile.txt');
The same with File Manager:

Code: (php) [Select]
$fmanager->deleteFile('myfile.txt');
In this case it appears that the standard way is shorter but we forgot something important. PHP will fail to delete the file if it is not writable by PHP (owner should be nobody or permissions 666). In the other hand File Manager will delete the file in any occasion as it is both PHP and FTP enabled!

2c. Where I can find more information?
Open Elxis file /includes/Core/filemanager.class.php to see all the available File Manager's functions and how they are used.

2d. Chapter's conclusion – compatibility guide
In order to convert a Mambo/Joomla component to an Elxis compatible one it is no need to change something in the way that handles files. But if we wish to make our life easier, reduce the lines of code and have automatic FTP support (this leads to solving many file related issues) then we must change the standard PHP functions by the File Manager's corresponding ones. Notice: If you call File Manager from inside a function don’t forget to use the global declaration first (global $fmanager; ) in order to become available.
Title: Database, ADOdb and queries
Post by: datahell on May 24, 2008, 23:19:26
10. Database, ADOdb and queries

10a. Database field names
Always use lowercase database field names.
Bad names: "myTitle", "DESCRIPTION"
Good names: "title", "description"

Never use well known reserved names as database field names as they cause big problems under certain database drivers. For example avoid naming your database fields as "option", "date", "time", "access", etc.

MySQL reserved words (http://dev.mysql.com/doc/refman/5.0/en/reserved-words.html)
PostgreSQL reserved words (http://www.postgresql.org/docs/7.3/static/sql-keywords-appendix.html)
Oracle reserved words (http://www.ispirer.com/doc/sqlways38/Output/SQLWays-1-128.html)

Notice: Elxis 2008.1 and newer has a limitation on the database fields names. A field name can not start from "qq". "qq" is used internally by Elxis as a prefix for compatibility reasons under some database drivers.
Tip: Using a prefix for your table fields is a good practice to avoid problems with reserved names.


10b. Random ordering
If you wish to select a random row from the database use the ADOdb $random property and no native mysql function rand() - or the random() function for postgreSQL. This will make your query cross-database supported.

Example:
Code: (sql) [Select]
$query = "SELECT * FROM #__banner WHERE showbanner = '1' ORDER BY ".$database->_resource->random;

10c. Getting data AS something other
Do not use the word "AS" when you want to point to a database table with a different name (it is safe to use it for database fields).

Code: (sql) [Select]
# Bad example:
SELECT b.bid, b.name AS bannername FROM #__banner AS b WHERE b.cid='1';

# Good examples:
SELECT b.bid, b.name AS bannername FROM #__banner b WHERE b.cid='1';
# or
SELECT b.bid, b.name bannername FROM #__banner b WHERE b.cid='1';


10d. Concat
If you want to use concat in your query use the ADOdb Concat method to gain cross-database support.
Example:
Code: (sql) [Select]
$query = "SELECT a.name AS title, a.description AS text, '' AS created, '2' AS browsernav,"
."\n s.id AS secid, a.id AS catid, m.id AS menuid, m.type AS menutype,"
. "\n ".$database->_resource->Concat('s.seotitle', "'/'", 'a.seotitle', "'/'")." AS seolink"
. "\n FROM #__categories a"
......


10e. XML schema and Installation
In order to make cross-database compatible your applications for Elxis CMS always use XML schema for installation instead of hard-coded sql queries ix XML installation file. XML schema creation is very easy using the ADOdb Data Dictionary library.

Complete manual for ADOdb Data Dictionary (http://phplens.com/lens/adodb/docs-datadict.htm)

Usage example:
Code: (php) [Select]
require_once($mainframe->getCfg('absolute_path').'/includes/adodb/adodb-xmlschema.inc.php');
$schemafile = 'path/to/your/schema/file/myschema.xml';

$schema = new adoSchema( $database->_resource );
$schema->ContinueOnError( true );
$schema->SetPrefix($database->_table_prefix);
$schema->ParseSchema( $schemafile );
$schema->ExecuteSchema();

Note 1: Elxis 2008.1 introduces ADOdb 5 and version 0.3 of XML schema (adodb-xmlschema03.inc.php). We recommend you to check if this version exist on the client site and use version 0.3 in that case. Schema 0.3 supports options (opt) and the platform attribute which gives you the possibility to declare platform specific queries in your XML schema.

Opt usage example:
Code: (xml) [Select]
<sql platform="oci8">
   <query>INSERT INTO banner ...</query>
</sql>

Note 2: We don't use the "#__" db table prefix in XML schema! In the XML file you write the table names without prefix and ADOdb will add the prefix automatically.


To be continued....
Title: Re: Elxis developers guide
Post by: datahell on May 29, 2008, 14:17:26
11. Access system

11a. Introduction
In Elxis CMS the access control is based on the users group. You can set access to almost any area of the site by setting the minimum group a user should belong to, in order to have access to that area (module, component, a content section or category, etc). Elxis CMS uses an extended version of the gacl (Generic Access Control Lists) PHP class to check user access to various areas of the site. With Elxis you can not only restrict access but you can also CREATE, EDIT and DELETE group names, permissions and their position on the Elxis hierarchy tree. A user belonging to a user group can access areas for his access level and all the others under his level. Note that ALL users belong to a group, even the site visitors are counted as users belonging to the "public_frontend" group.

Example 1:
GroupA
- GroupB
- GroupC
-- GroupD

A user belonging to GroupA has access only to objects with access level "GroupA".
A user belonging to GroupB has access to GroupB and GroupA objects.
A user belonging to GroupC has access to GroupC and GroupA objects.
A user belonging to GroupD has access to GroupD, GroupC and GroupA objects.

Each group has a group id (gid). In Elxis you can safely rename groups. So access is controlled by group ids and not by group names as group names may change.

Example 2:
GroupA (gid 1)
- GroupB (gid 2)
- GroupC (gid 3)
-- GroupD (gid 4)

A user belonging to GroupD (4) has access to GroupD (4), GroupC (3) and GroupA (1) objects. We can write his access permissions in a simple way by writing the group ids he has access to comma separated: 4,3,1. In Elxis this comma separated list of the user's allowed groups can be accessed by the property allowed: $my->allowed (string). Notice that you dont have to calculate that string. Elxis does this automatically and stores it in the global accessible $my object.

Now when we want to check if a user has access to a particular object we check if the object's access level is in the user's allowed groups.


11b. Elxis access system in action
Let's say an object has access level 3. Users belonging to groups C and D will be able to access that object, while users belonging to groups A and B wont. The objects access level is stored in Elxis database in fields named "access". So, in a hypothetical query we check if the user has access to that particular database item (i.e. content item) like this:

Code: (php) [Select]
<?php 
$query 
"SELECT * FROM #__XXXXXX"
."\n WHERE ......"
."\n AND access IN (".$my->allowed.")";
?>

It is important to understand the difference of the Elxis access system in comparison to mambo/joomla. In mambo/joomla the above query would look like this:

Code: (php) [Select]
<?php 
//mambo/joomla
$query "SELECT * FROM #__XXXXXX"
."\n WHERE ......"
."\n AND access > 0";
?>

This is a very dangerous query! Access in Elxis is always greater than 0 so everyone will have access to our private items! This is one of the reasons why we do not recommend the usage of mambo/joomla components in Elxis CMS without first making them compatible. This an example of Elxis vs mambo/joomla incompatibility WITHOUT generating any error. Do not wait to see errors to say that a component is incompatible to Elxis! Elxis has a much more sophisticated access system than mambo/joomla has. So, be careful!


To be continued....