community.egroupware.org: Community wiki

  
Community wiki
day two
the day before | Up | the day after


On day two of our training session we stepped into how we should send and recieve data, and how we
should design our application a bit more the eGroupware way.

Lets start with the traditional way to climb the hill

We decided that we wanted to have some input possibilities to affect the output of our greeting of the world.
Our index.php file now includes a form to start with and a form that comes into action to
display the users input and a button to reload the whole thing.


<?php

$GLOBALS['egw_info'] = array('flags' => array(
	'currentapp'=>	'test' ,
	'noheader'	=>	False,
	'nonavbar'	=>	False,
));
include('../header.inc.php');

        if (trim($_POST['fname'].$_POST['sname'])!='')
        {
            echo "<br>Hello ".$_POST['fname']." ".$_POST['sname']."<br>";
            echo "<form action='".$_SERVER['PHP_SELF']."' method='post'>
            <input type='submit' value=' Reload '>
            </form>";
        } 
        else 
        {
            echo "Type a name to be greeted accordingly <br>";
            echo "<form action='".$_SERVER['PHP_SELF']."' method='post'>
              <p>first name:<br><input name='fname' type='text' size='30' maxlength='30'></p>
              <p>name:<br><input name='sname' type='text' size='30' maxlength='40'></p>
                    <input type='submit' value=' Submit '>
                    <input type='reset' value=' Cancel'>
            </form>";
        
        }

 common::egw_footer();}}



Now we had to admit that this is working but had nothing to do with the eGroupware style of coding applications. So Ralf told us to do the same thing a bit more the eGroupware style.
Sure, there is the CodingRules, the DevelGuide and the StyleGuide. You should have a look at thoose.

CodingRules tell you about how some rules that the eGroupware developers would like you to follow.
DevelGuide is to improve eGroupware's usability reflecting the user's needs and being able to implement any necessary modifications as effortless as possible.
StyleGuide is to give you a guideline how to design your application.

Taking these into account, you can easily see, that our first approach is messy.

on our way to the eGroupware campsite, our first encounter with the class

You probably remember the required folderstructure to meet the needs of eGroupware to recognise
our application.
Remember the folder /inc?
The usual way eGroupware deals with userinterfaces, userrequests and stuff is through classes.
The common classes for an application are:
  • User Interface Class
  • Business Object Class
  • Storage Object Class
The names for these classes follow a naming schema in order to enable the eGroupware libraries
the recognition of your own application classes.
  • class.test_ui.inc.php for the User Interface Class
  • class.test_ui.inc.php for the Business Object Class
  • class.test_so.inc.php for theStorage Object Class

The classname of the class should meet the classname you use in the filename. But
most important is, do NOT use just class.{ui|bo|so}.inc.php, as the
class-names have to be unique! There is a reason for this. If you have a look how class-functions are called from
eGroupware (e.g. as menuaction), you will understand the need.

If you design an application the eGroupwareway the index.php file is reduced to something like this


<?php
header('Location: ../index.php?menuaction=test.test_ui.testinterface');


This means, anybody calling your application from within eGroupware is redirected
to the egroupware/index.php with a request for a certain menuaction.

The $_GET['menuaction'] parameter is taken into account, split and evaluated in the
  • form that it gets validated there is an application test in eGroupware
  • within test there is a classfile class.test_ui.inc.php in test/inc with the class test_ui
  • within that class test_ui there is a public callable function testinterface

By now there is no such class in the file nor the required function or the stuff we did not know about at this time.
So we created a class.
We created the required function testinterface.
We added the functionality.


<?php
class test_ui
{
   public function testinterface () 
   {
        if (trim($_POST['fname'].$_POST['sname'])!='')
        {
            echo "<br>Hello ".$_POST['fname']." ".$_POST['sname']."<br>";
            echo "<form action='".$_SERVER['PHP_SELF']."' method='post'>
            <input type='submit' value=' Reload '>
            </form>";
        } 
        else 
        {
            echo "Type a name to be greeted accordingly <br>";
            echo "<form action='".$_SERVER['PHP_SELF']."' method='post'>
              <p>first name:<br><input name='fname' type='text' size='30' maxlength='30'></p>
              <p>name:<br><input name='sname' type='text' size='30' maxlength='40'></p>
                    <input type='submit' value=' Submit '>
                    <input type='reset' value=' Cancel'>
            </form>";
        
        }
   }
}


And we were badly disappointed, since we were thrown to home instead of our application.

You must tell your class which function is to be called via a direct call from the outside.
This is done with an array public_functions where the public accessible functions are stored with the functionname as array-key and a boolean as value.
So we added ...


	var $public_functions = array(
		'testinterface'	=> True,
		);


... to our code.

Much better, but the integration with the eGroupware with the header and the sidebar and the footer - gone.
So we added the header and the functionality to create the footer.


public function create_header () 
	{
		common::egw_header();
		echo parse_navbar();
		
	}
	
public function create_footer () 
	{
		common::egw_footer();		
	}




We added those to our function testinterface and everything appeared to be nice and shiny, up until we tried to push the button

As we investigated our source fe noticed that we used $_SERVER['PHP_SELF'] as address to post our form to. That was fine for our first day in school but now we lost the application information with the call of
$_SERVER['PHP_SELF'] since it evaluates to /egroupware/index.php.

Knowing this, we introduced


function testinterface () 
{
    $this->create_header();
    if (trim($_POST['fname'].$_POST['sname'])!='')
    {
        //echo ''.$_SERVER['PHP_SELF'].'<br>';
        echo "<br>Hello ".$_POST['fname']." ".$_POST['sname']."<br>";
        echo "<form action='".$GLOBALS['egw']->link('/index.php',array(
    'menuaction' => 'test.test_ui.testinterface','message'=>'YES'))."' method='post'>
        <input type='submit' value=' Reload '>
        </form>";
    } 
    else 
    {
        echo "Type a name to be greeted accordingly <br>";
        echo "<form action='".$GLOBALS['egw']->link('/index.php',array(
    'menuaction' => 'test.test_ui.testinterface','message'=>'NO'))."' method='post'>
          <p>first name:<br><input name='fname' type='text' size='30' maxlength='30'></p>
          <p>name:<br><input name='sname' type='text' size='30' maxlength='40'></p>
                <input type='submit' value=' Submit '>
                <input type='reset' value=' Cancel'>
        </form>";
    
    }
    $this->create_footer();
}



So what is new here?
It is the link functionality:
$GLOBALS['egw']->link('/index.php',array('menuaction' => 'test.test_ui.testinterface','message'=>'YES'))
It does enable you to call the required function/action of any application and add a key/value pair to that call.

The whole thing looked like that:


<?php
class test_ui
{
	var $public_functions = array(
		'testinterface'	=> True,
		);

	public function create_header ()
	{
		common::egw_header();
		echo parse_navbar();

	}

	public function create_footer ()
	{
		common::egw_footer();
	}


    function testinterface ()
    {
        $this->create_header();
        if (trim($_POST['fname'].$_POST['sname'])!='')
        {
            //echo ''.$_SERVER['PHP_SELF'].'<br>';
            echo "<br>Hello ".$_POST['fname']." ".$_POST['sname']."<br>";
            echo "<form action='".$GLOBALS['egw']->link('/index.php',array(
        'menuaction' => 'test.test_ui.testinterface','message'=>'YES'))."' method='post'>
            <input type='submit' value=' Reload '>
            </form>";
        }
        else
        {
            echo "Type a name to be greeted accordingly <br>";
            echo "<form action='".$GLOBALS['egw']->link('/index.php',array(
        'menuaction' => 'test.test_ui.testinterface','message'=>'NO'))."' method='post'>
              <p>first name:<br><input name='fname' type='text' size='30' maxlength='30'></p>
              <p>name:<br><input name='sname' type='text' size='30' maxlength='40'></p>
                    <input type='submit' value=' Submit '>
                    <input type='reset' value=' Cancel'>
            </form>";

        }
        $this->create_footer();
    }
}


The link functionality provides the possibility to link to internal sites and pass on all internally needed information plus the call of a function with some infos to pass in $_GET.

So we introduced functions and the call of a function as well. The major way to call functions within eGroupware is, to call them via build in functions that handle the inclusion and instantiation of the needed classes.

ExecMethod('test.test_ui.send_request', 'YES');
Execute a function, and load a class and include the class file if not done so already. This function is used to create an instance of a class, and if the class file has not been included it will do so.

ExecMethod2('test.test_ui.send_request2', 'YES', 'SOME MORE');
Execute a function with multiple arguments. The function can take object $GLOBALS[classname] from class if it exists.

So we fiddled around with that a bit more and called it a day.

At the campfire we discussed CrossSiteScripting and how to handle/avoid that pitfall.

go on to the third day
Back to Code Corner or back to the first day
You are here