7 CodeCorner2
leithoff edited this page 2016-07-07 14:51:18 +02:00

Wiki ▸ [Developer Docs](Developer Docs) ▸ [Code Corner](Code Corner) ▸ day twoday three


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
/*
 prepare some application information for eGroupware to know
 If the applicationname of your application (e.g.: test) and the value of
 currentapp does not match, you will recieve an authentication error
*/

$GLOBALS['egw_info'] = array('flags' => array(
    'currentapp'=>  'test' ,
    'noheader'  =>  False,
    'nonavbar'  =>  False,
));
/*
 include THE eGroupware header, that takes care of the sessionhandling
 and the other background stuff
 the information provided above is used/required here in order to get the application running
*/
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>";
}
//display the eGroupware footer
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 Coding-Standards, the Developer Guide and the Style Guide. You should have a look at thoose.

Coding-Standards tell you about how some rules that the eGroupware developers would like you to follow. Developer Guide is to improve eGroupware's usability reflecting the user's needs and being able to implement any necessary modifications as effortless as possible. Style Guide 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 some strange error on the screen 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. We recieve our inital page o.k. But on Submit. It just did not work. After some work we figured out that $_SERVER['PHP_SELF'] is pointing to eGroupware Base index.php. So we had to make our form-action more specific:

	    echo "<form action='".$_SERVER['PHP_SELF']."?menuaction=test.test_ui.testinterface' method='post'>

this is in no way eGroupwarer - style. So this needs further refinement. We ended up with this whole class

<?php
class test_ui
{
	var $public_functions = array(
		'testinterface'	=> True,
		);
	public function testinterface () 
	{
		if (trim($_POST['fname'].$_POST['sname'])!='')
		{
		    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>";
		
		}
	}
}

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: 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 Cross Site Scripting and how to handle/avoid that pitfall.


Wiki ▸ [Developer Docs](Developer Docs) ▸ [Code Corner](Code Corner) ▸ day twoday three